[4.4.2] Remove 15 m/s limit on estimated vario (#12788)
[betaflight.git] / src / main / drivers / flash.c
blob39be0e9d838934cc4978d9da0ecfef9adeaa9143
1 /*
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)
8 * any later version.
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/>.
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <string.h>
25 #include "platform.h"
27 #include "build/debug.h"
29 #ifdef USE_FLASH_CHIP
31 #include "flash.h"
32 #include "flash_impl.h"
33 #include "flash_m25p16.h"
34 #include "flash_w25n01g.h"
35 #include "flash_w25q128fv.h"
36 #include "flash_w25m.h"
37 #include "drivers/bus_spi.h"
38 #include "drivers/bus_quadspi.h"
39 #include "drivers/bus_octospi.h"
40 #include "drivers/io.h"
41 #include "drivers/time.h"
42 #include "drivers/system.h"
44 #ifdef USE_FLASH_SPI
46 // 20 MHz max SPI frequency
47 #define FLASH_MAX_SPI_CLK_HZ 20000000
48 // 5 MHz max SPI init frequency
49 #define FLASH_MAX_SPI_INIT_CLK 5000000
51 static extDevice_t devInstance;
52 static extDevice_t *dev;
54 #endif
56 static flashDevice_t flashDevice;
57 static flashPartitionTable_t flashPartitionTable;
58 static int flashPartitions = 0;
60 #define FLASH_INSTRUCTION_RDID 0x9F
62 #ifdef USE_FLASH_MEMORY_MAPPED
63 MMFLASH_CODE_NOINLINE void flashMemoryMappedModeDisable(void)
65 __disable_irq();
66 #ifdef USE_FLASH_OCTOSPI
67 octoSpiDisableMemoryMappedMode(flashDevice.io.handle.octoSpi);
68 #else
69 #error Invalid configuration - Not implemented
70 #endif
73 MMFLASH_CODE_NOINLINE void flashMemoryMappedModeEnable(void)
75 #ifdef USE_FLASH_OCTOSPI
76 octoSpiEnableMemoryMappedMode(flashDevice.io.handle.octoSpi);
77 __enable_irq();
78 #else
79 #error Invalid configuration - Not implemented
80 #endif
82 #endif
84 #ifdef USE_FLASH_OCTOSPI
85 MMFLASH_CODE_NOINLINE static bool flashOctoSpiInit(const flashConfig_t *flashConfig)
87 bool detected = false;
89 enum {
90 TRY_1LINE = 0, TRY_4LINE, BAIL
91 } phase = TRY_1LINE;
93 #ifdef USE_FLASH_MEMORY_MAPPED
94 bool memoryMappedModeEnabledOnBoot = isMemoryMappedModeEnabledOnBoot();
95 #else
96 bool memoryMappedModeEnabledOnBoot = false;
97 #endif
99 #ifndef USE_OCTOSPI_EXPERIMENTAL
100 if (!memoryMappedModeEnabledOnBoot) {
101 return false; // Not supported yet, enable USE_OCTOSPI_EXPERIMENTAL and test/update implementation as required.
103 #endif
105 OCTOSPI_TypeDef *instance = octoSpiInstanceByDevice(OCTOSPI_CFG_TO_DEV(flashConfig->octoSpiDevice));
107 flashDevice.io.handle.octoSpi = instance;
108 flashDevice.io.mode = FLASHIO_OCTOSPI;
110 if (memoryMappedModeEnabledOnBoot) {
111 flashMemoryMappedModeDisable();
114 do {
115 #ifdef USE_OCTOSPI_EXPERIMENTAL
116 if (!memoryMappedMode) {
117 octoSpiSetDivisor(instance, OCTOSPI_CLOCK_INITIALISATION);
119 #endif
120 // for the memory-mapped use-case, we rely on the bootloader to have already selected the correct speed for the flash chip.
122 // 3 bytes for what we need, but some IC's need 8 dummy cycles after the instruction, so read 4 and make two attempts to
123 // assemble the chip id from the response.
124 uint8_t readIdResponse[4];
126 bool status = false;
127 switch (phase) {
128 case TRY_1LINE:
129 status = octoSpiReceive1LINE(instance, FLASH_INSTRUCTION_RDID, 0, readIdResponse, 4);
130 break;
131 case TRY_4LINE:
132 status = octoSpiReceive4LINES(instance, FLASH_INSTRUCTION_RDID, 2, readIdResponse, 3);
133 break;
134 default:
135 break;
138 if (!status) {
139 phase++;
140 continue;
143 #ifdef USE_OCTOSPI_EXPERIMENTAL
144 if (!memoryMappedModeEnabledOnBoot) {
145 octoSpiSetDivisor(instance, OCTOSPI_CLOCK_ULTRAFAST);
147 #endif
149 for (uint8_t offset = 0; offset <= 1 && !detected; offset++) {
151 uint32_t jedecID = (readIdResponse[offset + 0] << 16) | (readIdResponse[offset + 1] << 8) | (readIdResponse[offset + 2]);
153 if (offset == 0) {
154 #if defined(USE_FLASH_W25Q128FV)
155 if (!detected && w25q128fv_identify(&flashDevice, jedecID)) {
156 detected = true;
158 #endif
161 if (offset == 1) {
162 #ifdef USE_OCTOSPI_EXPERIMENTAL
163 if (!memoryMappedModeEnabledOnBoot) {
164 // These flash chips DO NOT support memory mapped mode; suitable flash read commands must be available.
165 #if defined(USE_FLASH_W25N01G)
166 if (!detected && w25n01g_identify(&flashDevice, jedecID)) {
167 detected = true;
169 #endif
170 #if defined(USE_FLASH_W25M02G)
171 if (!detected && w25m_identify(&flashDevice, jedecID)) {
172 detected = true;
174 #endif
176 #endif
179 phase++;
180 } while (phase != BAIL && !detected);
182 if (memoryMappedModeEnabledOnBoot) {
183 flashMemoryMappedModeEnable();
185 return detected;
188 #endif // USE_FLASH_OCTOSPI
190 #ifdef USE_FLASH_QUADSPI
191 static bool flashQuadSpiInit(const flashConfig_t *flashConfig)
193 bool detected = false;
195 enum { TRY_1LINE = 0, TRY_4LINE, BAIL};
196 int phase = TRY_1LINE;
198 QUADSPI_TypeDef *hqspi = quadSpiInstanceByDevice(QUADSPI_CFG_TO_DEV(flashConfig->quadSpiDevice));
200 flashDevice.io.handle.quadSpi = hqspi;
201 flashDevice.io.mode = FLASHIO_QUADSPI;
203 do {
204 quadSpiSetDivisor(hqspi, QUADSPI_CLOCK_INITIALISATION);
206 // 3 bytes for what we need, but some IC's need 8 dummy cycles after the instruction, so read 4 and make two attempts to
207 // assemble the chip id from the response.
208 uint8_t readIdResponse[4];
210 bool status = false;
211 switch (phase) {
212 case TRY_1LINE:
213 status = quadSpiReceive1LINE(hqspi, FLASH_INSTRUCTION_RDID, 0, readIdResponse, 4);
214 break;
215 case TRY_4LINE:
216 status = quadSpiReceive4LINES(hqspi, FLASH_INSTRUCTION_RDID, 2, readIdResponse, 3);
217 break;
218 default:
219 break;
222 if (!status) {
223 phase++;
224 continue;
227 quadSpiSetDivisor(hqspi, QUADSPI_CLOCK_ULTRAFAST);
230 for (uint8_t offset = 0; offset <= 1 && !detected; offset++) {
232 uint32_t jedecID = (readIdResponse[offset + 0] << 16) | (readIdResponse[offset + 1] << 8) | (readIdResponse[offset + 2]);
234 if (offset == 0) {
235 #if defined(USE_FLASH_W25Q128FV)
236 if (!detected && w25q128fv_identify(&flashDevice, jedecID)) {
237 detected = true;
239 #endif
241 #ifdef USE_FLASH_M25P16
242 if (!detected && m25p16_detect(&flashDevice, chipID)) {
243 detected = true;
245 #endif
248 if (offset == 1) {
249 #if defined(USE_FLASH_W25N01G)
250 if (!detected && w25n01g_identify(&flashDevice, jedecID)) {
251 detected = true;
253 #endif
254 #if defined(USE_FLASH_W25M02G)
255 if (!detected && w25m_identify(&flashDevice, jedecID)) {
256 detected = true;
258 #endif
261 if (detected) {
262 flashDevice.geometry.jedecId = jedecID;
265 phase++;
266 } while (phase != BAIL && !detected);
268 return detected;
270 #endif // USE_FLASH_QUADSPI
272 #ifdef USE_FLASH_SPI
273 static bool flashSpiInit(const flashConfig_t *flashConfig)
275 bool detected = false;
276 // Read chip identification and send it to device detect
277 dev = &devInstance;
279 if (flashConfig->csTag) {
280 dev->busType_u.spi.csnPin = IOGetByTag(flashConfig->csTag);
281 } else {
282 return false;
285 if (!IOIsFreeOrPreinit(dev->busType_u.spi.csnPin)) {
286 return false;
289 if (!spiSetBusInstance(dev, flashConfig->spiDevice)) {
290 return false;
293 // Set the callback argument when calling back to this driver for DMA completion
294 dev->callbackArg = (uint32_t)&flashDevice;
296 IOInit(dev->busType_u.spi.csnPin, OWNER_FLASH_CS, 0);
297 IOConfigGPIO(dev->busType_u.spi.csnPin, SPI_IO_CS_CFG);
298 IOHi(dev->busType_u.spi.csnPin);
300 //Maximum speed for standard READ command is 20mHz, other commands tolerate 25mHz
301 spiSetClkDivisor(dev, spiCalculateDivider(FLASH_MAX_SPI_INIT_CLK));
303 flashDevice.io.mode = FLASHIO_SPI;
304 flashDevice.io.handle.dev = dev;
306 delay(50); // short delay required after initialisation of SPI device instance.
309 * Some newer chips require one dummy byte to be read; we can read
310 * 4 bytes for these chips while retaining backward compatibility.
312 uint8_t readIdResponse[4] = { 0 };
314 spiReadRegBuf(dev, FLASH_INSTRUCTION_RDID, readIdResponse, sizeof(readIdResponse));
316 // Manufacturer, memory type, and capacity
317 uint32_t jedecID = (readIdResponse[0] << 16) | (readIdResponse[1] << 8) | (readIdResponse[2]);
319 #ifdef USE_FLASH_M25P16
320 if (m25p16_identify(&flashDevice, jedecID)) {
321 detected = true;
323 #endif
325 #if defined(USE_FLASH_W25M512) || defined(USE_FLASH_W25M)
326 if (!detected && w25m_identify(&flashDevice, jedecID)) {
327 detected = true;
329 #endif
331 if (!detected) {
332 // Newer chips
333 jedecID = (readIdResponse[1] << 16) | (readIdResponse[2] << 8) | (readIdResponse[3]);
336 #ifdef USE_FLASH_W25N01G
337 if (!detected && w25n01g_identify(&flashDevice, jedecID)) {
338 detected = true;
340 #endif
342 #ifdef USE_FLASH_W25M02G
343 if (!detected && w25m_identify(&flashDevice, jedecID)) {
344 detected = true;
346 #endif
348 if (detected) {
349 flashDevice.geometry.jedecId = jedecID;
350 return detected;
353 spiPreinitByTag(flashConfig->csTag);
355 return false;
357 #endif // USE_FLASH_SPI
359 void flashPreInit(const flashConfig_t *flashConfig)
361 spiPreinitRegister(flashConfig->csTag, IOCFG_IPU, 1);
364 bool flashDeviceInit(const flashConfig_t *flashConfig)
366 bool haveFlash = false;
368 #ifdef USE_FLASH_SPI
369 bool useSpi = (SPI_CFG_TO_DEV(flashConfig->spiDevice) != SPIINVALID);
371 if (useSpi) {
372 haveFlash = flashSpiInit(flashConfig);
374 #endif
376 #ifdef USE_FLASH_QUADSPI
377 bool useQuadSpi = (QUADSPI_CFG_TO_DEV(flashConfig->quadSpiDevice) != QUADSPIINVALID);
378 if (useQuadSpi) {
379 haveFlash = flashQuadSpiInit(flashConfig);
381 #endif
383 #ifdef USE_FLASH_OCTOSPI
384 bool useOctoSpi = (OCTOSPI_CFG_TO_DEV(flashConfig->octoSpiDevice) != OCTOSPIINVALID);
385 if (useOctoSpi) {
386 haveFlash = flashOctoSpiInit(flashConfig);
388 #endif
390 if (haveFlash && flashDevice.vTable->configure) {
391 uint32_t configurationFlags = 0;
393 #ifdef USE_FLASH_MEMORY_MAPPED
394 if (isMemoryMappedModeEnabledOnBoot()) {
395 configurationFlags |= FLASH_CF_SYSTEM_IS_MEMORY_MAPPED;
397 #endif
399 flashDevice.vTable->configure(&flashDevice, configurationFlags);
402 return haveFlash;
405 MMFLASH_CODE bool flashIsReady(void)
407 return flashDevice.vTable->isReady(&flashDevice);
410 MMFLASH_CODE bool flashWaitForReady(void)
412 return flashDevice.vTable->waitForReady(&flashDevice);
415 MMFLASH_CODE void flashEraseSector(uint32_t address)
417 flashDevice.callback = NULL;
418 flashDevice.vTable->eraseSector(&flashDevice, address);
421 void flashEraseCompletely(void)
423 flashDevice.callback = NULL;
424 flashDevice.vTable->eraseCompletely(&flashDevice);
427 /* The callback, if provided, will receive the totoal number of bytes transfered
428 * by each call to flashPageProgramContinue() once the transfer completes.
430 MMFLASH_CODE void flashPageProgramBegin(uint32_t address, void (*callback)(uint32_t length))
432 flashDevice.vTable->pageProgramBegin(&flashDevice, address, callback);
435 MMFLASH_CODE uint32_t flashPageProgramContinue(const uint8_t **buffers, uint32_t *bufferSizes, uint32_t bufferCount)
437 uint32_t maxBytesToWrite = flashDevice.geometry.pageSize - (flashDevice.currentWriteAddress % flashDevice.geometry.pageSize);
439 if (bufferCount == 0) {
440 return 0;
443 if (bufferSizes[0] >= maxBytesToWrite) {
444 bufferSizes[0] = maxBytesToWrite;
445 bufferCount = 1;
446 } else {
447 maxBytesToWrite -= bufferSizes[0];
448 if ((bufferCount == 2) && (bufferSizes[1] > maxBytesToWrite)) {
449 bufferSizes[1] = maxBytesToWrite;
453 return flashDevice.vTable->pageProgramContinue(&flashDevice, buffers, bufferSizes, bufferCount);
456 MMFLASH_CODE void flashPageProgramFinish(void)
458 flashDevice.vTable->pageProgramFinish(&flashDevice);
461 MMFLASH_CODE void flashPageProgram(uint32_t address, const uint8_t *data, uint32_t length, void (*callback)(uint32_t length))
463 flashDevice.vTable->pageProgram(&flashDevice, address, data, length, callback);
466 MMFLASH_CODE int flashReadBytes(uint32_t address, uint8_t *buffer, uint32_t length)
468 flashDevice.callback = NULL;
469 return flashDevice.vTable->readBytes(&flashDevice, address, buffer, length);
472 MMFLASH_CODE void flashFlush(void)
474 if (flashDevice.vTable->flush) {
475 flashDevice.vTable->flush(&flashDevice);
479 static const flashGeometry_t noFlashGeometry = {
480 .totalSize = 0,
483 const flashGeometry_t *flashGetGeometry(void)
485 if (flashDevice.vTable && flashDevice.vTable->getGeometry) {
486 return flashDevice.vTable->getGeometry(&flashDevice);
489 return &noFlashGeometry;
493 * Flash partitioning
495 * Partition table is not currently stored on the flash, in-memory only.
497 * Partitions are required so that Badblock management (inc spare blocks), FlashFS (Blackbox Logging), Configuration and Firmware can be kept separate and tracked.
499 * XXX FIXME
500 * XXX Note that Flash FS must start at sector 0.
501 * XXX There is existing blackbox/flash FS code the relies on this!!!
502 * XXX This restriction can and will be fixed by creating a set of flash operation functions that take partition as an additional parameter.
505 static void flashConfigurePartitions(void)
507 #if defined(FIRMWARE_SIZE) || defined(CONFIG_IN_EXTERNAL_FLASH) || defined(USE_FLASHFS)
508 const flashGeometry_t *flashGeometry = flashGetGeometry();
509 if (flashGeometry->totalSize == 0) {
510 return;
513 flashSector_t startSector = 0;
514 flashSector_t endSector = flashGeometry->sectors - 1; // 0 based index
516 const flashPartition_t *badBlockPartition = flashPartitionFindByType(FLASH_PARTITION_TYPE_BADBLOCK_MANAGEMENT);
517 if (badBlockPartition) {
518 endSector = badBlockPartition->startSector - 1;
520 #endif
522 #if defined(FIRMWARE_SIZE)
523 const uint32_t firmwareSize = (FIRMWARE_SIZE * 1024);
524 flashSector_t firmwareSectors = (firmwareSize / flashGeometry->sectorSize);
526 if (firmwareSize % flashGeometry->sectorSize > 0) {
527 firmwareSectors++; // needs a portion of a sector.
530 startSector = (endSector + 1) - firmwareSectors; // + 1 for inclusive
532 flashPartitionSet(FLASH_PARTITION_TYPE_FIRMWARE, startSector, endSector);
534 endSector = startSector - 1;
535 startSector = 0;
536 #endif
538 #if defined(CONFIG_IN_EXTERNAL_FLASH) || defined(CONFIG_IN_MEMORY_MAPPED_FLASH)
539 const uint32_t configSize = EEPROM_SIZE;
540 flashSector_t configSectors = (configSize / flashGeometry->sectorSize);
542 if (configSize % flashGeometry->sectorSize > 0) {
543 configSectors++; // needs a portion of a sector.
546 startSector = (endSector + 1) - configSectors; // + 1 for inclusive
548 flashPartitionSet(FLASH_PARTITION_TYPE_CONFIG, startSector, endSector);
550 endSector = startSector - 1;
551 startSector = 0;
552 #endif
554 #ifdef USE_FLASHFS
555 flashPartitionSet(FLASH_PARTITION_TYPE_FLASHFS, startSector, endSector);
556 #endif
559 flashPartition_t *flashPartitionFindByType(uint8_t type)
561 for (int index = 0; index < FLASH_MAX_PARTITIONS; index++) {
562 flashPartition_t *candidate = &flashPartitionTable.partitions[index];
563 if (candidate->type == type) {
564 return candidate;
568 return NULL;
571 const flashPartition_t *flashPartitionFindByIndex(uint8_t index)
573 if (index >= flashPartitions) {
574 return NULL;
577 return &flashPartitionTable.partitions[index];
580 void flashPartitionSet(uint8_t type, uint32_t startSector, uint32_t endSector)
582 flashPartition_t *entry = flashPartitionFindByType(type);
584 if (!entry) {
585 if (flashPartitions == FLASH_MAX_PARTITIONS - 1) {
586 return;
588 entry = &flashPartitionTable.partitions[flashPartitions++];
591 entry->type = type;
592 entry->startSector = startSector;
593 entry->endSector = endSector;
596 // Must be in sync with FLASH_PARTITION_TYPE
597 static const char *flashPartitionNames[] = {
598 "UNKNOWN ",
599 "PARTITION",
600 "FLASHFS ",
601 "BBMGMT ",
602 "FIRMWARE ",
603 "CONFIG ",
606 const char *flashPartitionGetTypeName(flashPartitionType_e type)
608 if (type < ARRAYLEN(flashPartitionNames)) {
609 return flashPartitionNames[type];
612 return NULL;
615 bool flashInit(const flashConfig_t *flashConfig)
617 memset(&flashPartitionTable, 0x00, sizeof(flashPartitionTable));
618 flashPartitions = 0;
620 bool haveFlash = flashDeviceInit(flashConfig);
622 flashConfigurePartitions();
624 return haveFlash;
627 int flashPartitionCount(void)
629 return flashPartitions;
631 #endif // USE_FLASH_CHIP