├── .codespell ├── exclude-file.txt └── ignore-words.txt ├── .gitignore ├── examples ├── flash_erase_express │ ├── .clue.generate │ ├── .cpb.generate │ ├── .cpx_ada.generate │ ├── .metro_m0.generate │ ├── .metro_m4.generate │ ├── .nrf52840.generate │ ├── .pybadge.generate │ ├── .pyportal.generate │ ├── .feather_rp2040.generate │ ├── .grand_central.generate │ ├── .matrixportal.generate │ ├── .metroesp32s2.generate │ ├── .neotrellis_m4.generate │ ├── .feather_m0_express.generate │ ├── .feather_m4_express.generate │ ├── .pyportal_titano.generate │ ├── flash_erase_express.ino │ └── flash_config.h ├── SdFat_OpenNext │ ├── SdFat_OpenNext.ino │ └── flash_config.h ├── SdFat_Flash_and_SDcard │ ├── SdFat_Flash_and_SDcard.ino │ └── flash_config.h ├── flash_sector_dump │ ├── flash_sector_dump.ino │ └── flash_config.h ├── SdFat_ReadWrite │ ├── SdFat_ReadWrite.ino │ └── flash_config.h ├── SdFat_format │ ├── diskio.h │ ├── flash_config.h │ ├── SdFat_format.ino │ └── ffconf.h ├── flash_erase │ ├── flash_erase.ino │ └── flash_config.h ├── SdFat_print_file │ ├── SdFat_print_file.ino │ └── flash_config.h ├── SdFat_datalogging │ ├── SdFat_datalogging.ino │ └── flash_config.h ├── flash_info │ ├── flash_config.h │ └── flash_info.ino ├── SdFat_full_usage │ ├── flash_config.h │ └── SdFat_full_usage.ino ├── flash_manipulator │ ├── flash_config.h │ └── flash_manipulator.ino ├── flash_speedtest │ ├── flash_config.h │ └── flash_speedtest.ino ├── SdFat_circuitpython │ ├── flash_config.h │ └── SdFat_circuitpython.ino └── SdFat_circuitpython_backupFiles │ ├── flash_config.h │ └── SdFat_circuitpython_backupFiles.ino ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── feature_request.md │ └── bug_report.yml └── workflows │ └── githubci.yml ├── .codespellrc ├── library.properties ├── .pre-commit-config.yaml ├── tools ├── update-flash_config.py └── build_all.py ├── README.md ├── LICENSE └── src ├── Adafruit_FlashCache.h ├── qspi ├── Adafruit_FlashTransport_QSPI.h ├── Adafruit_FlashTransport_QSPI_SAMD.cpp └── Adafruit_FlashTransport_QSPI_NRF.cpp ├── esp32 ├── Adafruit_FlashTransport_ESP32.h └── Adafruit_FlashTransport_ESP32.cpp ├── spi ├── Adafruit_FlashTransport_SPI.h └── Adafruit_FlashTransport_SPI.cpp ├── Adafruit_SPIFlashBase.h ├── rp2040 ├── Adafruit_FlashTransport_RP2040.h └── Adafruit_FlashTransport_RP2040.cpp ├── Adafruit_SPIFlash.h ├── Adafruit_FlashCache.cpp ├── Adafruit_FlashTransport.h └── Adafruit_SPIFlash.cpp /.codespell/exclude-file.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | -------------------------------------------------------------------------------- /examples/flash_erase_express/.clue.generate: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/flash_erase_express/.cpb.generate: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/flash_erase_express/.cpx_ada.generate: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/flash_erase_express/.metro_m0.generate: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/flash_erase_express/.metro_m4.generate: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/flash_erase_express/.nrf52840.generate: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/flash_erase_express/.pybadge.generate: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/flash_erase_express/.pyportal.generate: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/flash_erase_express/.feather_rp2040.generate: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/flash_erase_express/.grand_central.generate: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/flash_erase_express/.matrixportal.generate: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/flash_erase_express/.metroesp32s2.generate: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/flash_erase_express/.neotrellis_m4.generate: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/flash_erase_express/.feather_m0_express.generate: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/flash_erase_express/.feather_m4_express.generate: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/flash_erase_express/.pyportal_titano.generate: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.codespell/ignore-words.txt: -------------------------------------------------------------------------------- 1 | synopsys 2 | sie 3 | inout 4 | busses 5 | thre 6 | 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Adafruit Support Forum 4 | url: https://forums.adafruit.com 5 | about: If you have other questions or need help, post it here. 6 | -------------------------------------------------------------------------------- /.codespellrc: -------------------------------------------------------------------------------- 1 | # See: https://github.com/codespell-project/codespell#using-a-config-file 2 | [codespell] 3 | # In the event of a false positive, add the problematic word, in all lowercase, to 'ignore-words.txt' (one word per line). 4 | # Or copy & paste the whole problematic line to 'exclude-file.txt' 5 | ignore-words = .codespell/ignore-words.txt 6 | exclude-file = .codespell/exclude-file.txt 7 | check-filenames = 8 | check-hidden = 9 | count = 10 | skip = .git 11 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Adafruit SPIFlash 2 | version=5.1.1 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=SPI Flash filesystem support for FAT and CircuitPython FS support from within Arduino 6 | paragraph=SPI Flash filesystem support for FAT and CircuitPython FS support from within Arduino 7 | category=Data Storage 8 | url=https://github.com/adafruit/Adafruit_SPIFlash 9 | architectures=* 10 | depends=Adafruit NeoPixel, SdFat - Adafruit Fork 11 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2020 Diego Elio Pettenò 2 | # 3 | # SPDX-License-Identifier: Unlicense 4 | 5 | repos: 6 | - repo: https://github.com/pre-commit/mirrors-clang-format 7 | rev: v15.0.7 8 | hooks: 9 | - id: clang-format 10 | exclude: | 11 | (?x)^( 12 | examples/SdFat_format| 13 | tools 14 | ) 15 | types_or: [c++, c, header] 16 | 17 | - repo: https://github.com/codespell-project/codespell 18 | rev: v2.2.4 19 | hooks: 20 | - id: codespell 21 | args: [-w] 22 | exclude: | 23 | (?x)^( 24 | examples/SdFat_format/ff.c| 25 | examples/SdFat_format/ff.h 26 | ) 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: Feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /tools/update-flash_config.py: -------------------------------------------------------------------------------- 1 | # simple script to update all examples' flash_config.h based on the file in this folder 2 | from pathlib import Path 3 | import click 4 | 5 | import shutil 6 | 7 | @click.command() 8 | @click.argument('dir', required=True) 9 | def main(dir): 10 | """ 11 | This script takes a mandatory 'dir' argument, which is a path to pivot example to update for all DualRole's examples 12 | """ 13 | examples_dir = Path('examples') 14 | sample_dir = examples_dir / dir 15 | assert sample_dir.is_dir(), f"examples/{dir} does not exist or is not a valid dir." 16 | sample_file = sample_dir / 'flash_config.h' 17 | 18 | f_list = sorted(examples_dir.glob('*/flash_config.h')) 19 | for f in f_list: 20 | if f != sample_file: 21 | click.echo(f"Updating {f}") 22 | shutil.copy(sample_file, f) 23 | 24 | if __name__ == '__main__': 25 | main() 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Adafruit SPI Flash 2 | 3 | [![Build Status](https://github.com/adafruit/Adafruit_SPIFlash/workflows/Build/badge.svg)](https://github.com/adafruit/Adafruit_SPIFlash/actions) [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT) 4 | 5 | Arduino library for external (Q)SPI flash device. 6 | 7 | ## Supported Cores 8 | 9 | - [adafruit/Adafruit_nRF52_Arduino](https://github.com/adafruit/Adafruit_nRF52_Arduino) 10 | - [adafruit/ArduinoCore-samd](https://github.com/adafruit/ArduinoCore-samd) 11 | - [earlephilhower/arduino-pico](https://github.com/earlephilhower/arduino-pico) 12 | - [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) 13 | 14 | ## Features 15 | 16 | - Support SPI interfaces for all cores 17 | - Support QSPI interfaces for nRF52 and SAMD51 18 | - Support FRAM flash devices 19 | - Provide raw flash access APIs 20 | - Implement block device APIs from SdFat's BaseBlockDRiver with caching to facilitate FAT filesystem on flash device 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Adafruit Industries, LLC 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /examples/SdFat_OpenNext/SdFat_OpenNext.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Print size, modify date/time, and name for all files in root. 3 | */ 4 | #include 5 | 6 | #include "SdFat_Adafruit_Fork.h" 7 | 8 | #include "Adafruit_SPIFlash.h" 9 | 10 | // for flashTransport definition 11 | #include "flash_config.h" 12 | 13 | Adafruit_SPIFlash flash(&flashTransport); 14 | 15 | // file system object from SdFat 16 | FatVolume fatfs; 17 | 18 | File32 root; 19 | File32 file; 20 | 21 | //------------------------------------------------------------------------------ 22 | void setup() { 23 | Serial.begin(115200); 24 | 25 | // Init external flash 26 | flash.begin(); 27 | 28 | // Init file system on the flash 29 | fatfs.begin(&flash); 30 | 31 | // Wait for USB Serial 32 | while (!Serial) { 33 | yield(); 34 | } 35 | 36 | if (!root.open("/")) { 37 | Serial.println("open root failed"); 38 | } 39 | // Open next file in root. 40 | // Warning, openNext starts at the current directory position 41 | // so a rewind of the directory may be required. 42 | while (file.openNext(&root, O_RDONLY)) { 43 | file.printFileSize(&Serial); 44 | Serial.write(' '); 45 | file.printModifyDateTime(&Serial); 46 | Serial.write(' '); 47 | file.printName(&Serial); 48 | if (file.isDir()) { 49 | // Indicate a directory. 50 | Serial.write('/'); 51 | } 52 | Serial.println(); 53 | file.close(); 54 | } 55 | 56 | if (root.getError()) { 57 | Serial.println("openNext failed"); 58 | } else { 59 | Serial.println("Done!"); 60 | } 61 | } 62 | //------------------------------------------------------------------------------ 63 | void loop() {} 64 | -------------------------------------------------------------------------------- /examples/SdFat_Flash_and_SDcard/SdFat_Flash_and_SDcard.ino: -------------------------------------------------------------------------------- 1 | // Adafruit Grand Central M4 QSPI Flash and SD Card Setup Example 2 | // Author: Joshua Scoggins 3 | // 4 | // This is an example of how to bring up both the QSPI Flash and SD Card found 5 | // on the Adafruit Grand Central M4. This example will setup both the QSPI 6 | // Flash and SD card (if present) and display information about the QSPI flash. 7 | // 8 | 9 | #include "SdFat_Adafruit_Fork.h" 10 | #include 11 | 12 | #include 13 | 14 | // for flashTransport definition 15 | #include "flash_config.h" 16 | 17 | Adafruit_SPIFlash onboardFlash(&flashTransport); 18 | SdFat onboardSdCard; 19 | 20 | constexpr int getSDCardPin() noexcept { 21 | #ifdef SDCARD_SS_PIN 22 | return SDCARD_SS_PIN; 23 | #else 24 | // modify to fit your needs 25 | // by default, pin 4 is the SD_CS pin used by the Adafruit 1.8" TFT SD Shield 26 | return 4; 27 | #endif 28 | } 29 | void setup() { 30 | Serial.begin(115200); 31 | while (!Serial) { 32 | // wait for native usb 33 | delay(100); 34 | } 35 | Serial.print("Starting up onboard QSPI Flash..."); 36 | onboardFlash.begin(); 37 | Serial.println("Done"); 38 | Serial.println("Onboard Flash information"); 39 | Serial.print("JEDEC ID: 0x"); 40 | Serial.println(onboardFlash.getJEDECID(), HEX); 41 | Serial.print("Flash size: "); 42 | Serial.print(onboardFlash.size() / 1024); 43 | Serial.println(" KB"); 44 | Serial.print("Starting up SD Card..."); 45 | if (!onboardSdCard.begin(getSDCardPin())) { 46 | Serial.println("No card found (is one inserted?)"); 47 | } else { 48 | Serial.println("Card found!"); 49 | } 50 | } 51 | 52 | void loop() { 53 | // nothing to do 54 | } 55 | -------------------------------------------------------------------------------- /src/Adafruit_FlashCache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 hathach for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef ADAFRUIT_FLASHCACHE_H_ 26 | #define ADAFRUIT_FLASHCACHE_H_ 27 | 28 | #include 29 | #include 30 | 31 | // forward declaration 32 | class Adafruit_SPIFlashBase; 33 | 34 | class Adafruit_FlashCache { 35 | private: 36 | uint8_t _buf[4096] __attribute__((aligned(4))); // must be sector size 37 | uint32_t _addr; 38 | 39 | public: 40 | Adafruit_FlashCache(void); 41 | 42 | bool sync(Adafruit_SPIFlashBase *fl); 43 | bool write(Adafruit_SPIFlashBase *fl, uint32_t dst, void const *src, 44 | uint32_t len); 45 | bool read(Adafruit_SPIFlashBase *fl, uint32_t addr, uint8_t *dst, 46 | uint32_t count); 47 | }; 48 | 49 | #endif /* ADAFRUIT_FLASHCACHE_H_ */ 50 | -------------------------------------------------------------------------------- /examples/flash_sector_dump/flash_sector_dump.ino: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // Copyright (c) 2019 Ha Thach for Adafruit Industries 3 | 4 | #include "SPI.h" 5 | #include "SdFat_Adafruit_Fork.h" 6 | 7 | #include "Adafruit_SPIFlash.h" 8 | 9 | // for flashTransport definition 10 | #include "flash_config.h" 11 | 12 | Adafruit_SPIFlash flash(&flashTransport); 13 | 14 | // the setup function runs once when you press reset or power the board 15 | void setup() { 16 | Serial.begin(115200); 17 | while (!Serial) { 18 | delay(10); // wait for native usb 19 | } 20 | 21 | flash.begin(); 22 | 23 | Serial.println("Adafruit Serial Flash Sector Dump example"); 24 | Serial.print("JEDEC ID: "); 25 | Serial.println(flash.getJEDECID(), HEX); 26 | Serial.print("Flash size: "); 27 | Serial.println(flash.size()); 28 | } 29 | 30 | void dump_sector(uint32_t sector) { 31 | uint8_t buf[4096]; 32 | memset(buf, 0xff, sizeof(buf)); 33 | 34 | flash.readBuffer(sector * 4096, buf, 4096); 35 | 36 | for (uint32_t row = 0; row < sizeof(buf) / 16; row++) { 37 | if (row == 0) 38 | Serial.print("0"); 39 | if (row < 16) 40 | Serial.print("0"); 41 | Serial.print(row * 16, HEX); 42 | Serial.print(" : "); 43 | 44 | for (uint32_t col = 0; col < 16; col++) { 45 | uint8_t val = buf[row * 16 + col]; 46 | 47 | if (val < 16) 48 | Serial.print("0"); 49 | Serial.print(val, HEX); 50 | 51 | Serial.print(" "); 52 | } 53 | 54 | Serial.println(); 55 | } 56 | } 57 | 58 | void loop() { 59 | Serial.print("Enter the sector number to dump: "); 60 | while (!Serial.available()) { 61 | delay(10); 62 | } 63 | 64 | int sector = Serial.parseInt(); 65 | int sector_max = (int)flash.size() / 4096; 66 | 67 | Serial.println(sector); // echo 68 | 69 | if (sector < sector_max) { 70 | dump_sector(sector); 71 | } else { 72 | Serial.println("Invalid sector number"); 73 | } 74 | 75 | Serial.println(); 76 | delay(10); // a bit of delay 77 | } 78 | -------------------------------------------------------------------------------- /src/qspi/Adafruit_FlashTransport_QSPI.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 hathach for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef ADAFRUIT_FLASHTRANSPORT_QSPI_H_ 26 | #define ADAFRUIT_FLASHTRANSPORT_QSPI_H_ 27 | 28 | class Adafruit_FlashTransport_QSPI : public Adafruit_FlashTransport { 29 | private: 30 | int8_t _sck, _cs; 31 | int8_t _io0, _io1, _io2, _io3; 32 | 33 | public: 34 | Adafruit_FlashTransport_QSPI(int8_t pinSCK, int8_t pinCS, int8_t pinIO0, 35 | int8_t pinIO1, int8_t pinIO2, int8_t pinIO3); 36 | Adafruit_FlashTransport_QSPI(void); 37 | 38 | virtual void begin(void); 39 | virtual void end(void); 40 | 41 | virtual bool supportQuadMode(void) { return true; } 42 | 43 | virtual void setClockSpeed(uint32_t write_hz, uint32_t read_hz); 44 | 45 | virtual bool runCommand(uint8_t command); 46 | virtual bool readCommand(uint8_t command, uint8_t *response, uint32_t len); 47 | virtual bool writeCommand(uint8_t command, uint8_t const *data, uint32_t len); 48 | 49 | virtual bool eraseCommand(uint8_t command, uint32_t address); 50 | virtual bool readMemory(uint32_t addr, uint8_t *data, uint32_t len); 51 | virtual bool writeMemory(uint32_t addr, uint8_t const *data, uint32_t len); 52 | }; 53 | 54 | #endif /* ADAFRUIT_FLASHTRANSPORT_QSPI_H_ */ 55 | -------------------------------------------------------------------------------- /src/esp32/Adafruit_FlashTransport_ESP32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2020 hathach for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef ADAFRUIT_FLASHTRANSPORT_ESP32_H_ 26 | #define ADAFRUIT_FLASHTRANSPORT_ESP32_H_ 27 | 28 | #include "Arduino.h" 29 | #include "SPI.h" 30 | #include "flash_devices.h" 31 | 32 | class Adafruit_FlashTransport_ESP32 : public Adafruit_FlashTransport { 33 | private: 34 | esp_partition_t const *_partition; 35 | SPIFlash_Device_t _flash_device; 36 | 37 | public: 38 | Adafruit_FlashTransport_ESP32(void); 39 | 40 | virtual void begin(void); 41 | virtual void end(void); 42 | 43 | virtual bool supportQuadMode(void) { return false; } 44 | 45 | virtual void setClockSpeed(uint32_t write_hz, uint32_t read_hz); 46 | 47 | virtual bool runCommand(uint8_t command); 48 | virtual bool readCommand(uint8_t command, uint8_t *response, uint32_t len); 49 | virtual bool writeCommand(uint8_t command, uint8_t const *data, uint32_t len); 50 | virtual bool eraseCommand(uint8_t command, uint32_t addr); 51 | 52 | virtual bool readMemory(uint32_t addr, uint8_t *data, uint32_t len); 53 | virtual bool writeMemory(uint32_t addr, uint8_t const *data, uint32_t len); 54 | 55 | // Flash device is already detected and configured, get the pointer without 56 | // go through initial sequence 57 | SPIFlash_Device_t *getFlashDevice(void); 58 | }; 59 | 60 | #endif /* ADAFRUIT_FLASHTRANSPORT_ESP32_H_ */ 61 | -------------------------------------------------------------------------------- /examples/SdFat_ReadWrite/SdFat_ReadWrite.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SD card read/write 3 | 4 | This example shows how to read and write data to and from an SD card file 5 | The circuit: 6 | * SD card attached to SPI bus as follows: 7 | ** MOSI - pin 11 8 | ** MISO - pin 12 9 | ** CLK - pin 13 10 | 11 | created Nov 2010 12 | by David A. Mellis 13 | modified 9 Apr 2012 14 | by Tom Igoe 15 | 16 | This example code is in the public domain. 17 | 18 | */ 19 | 20 | #include 21 | 22 | #include "SdFat_Adafruit_Fork.h" 23 | 24 | #include "Adafruit_SPIFlash.h" 25 | 26 | // for flashTransport definition 27 | #include "flash_config.h" 28 | 29 | Adafruit_SPIFlash flash(&flashTransport); 30 | 31 | // file system object from SdFat 32 | FatVolume fatfs; 33 | File32 myFile; 34 | 35 | void setup() { 36 | // Open serial communications and wait for port to open: 37 | Serial.begin(115200); 38 | while (!Serial) { 39 | delay( 40 | 10); // wait for serial port to connect. Needed for native USB port only 41 | } 42 | 43 | Serial.println("Initializing Filesystem on external flash..."); 44 | 45 | // Init external flash 46 | flash.begin(); 47 | 48 | // Open file system on the flash 49 | if (!fatfs.begin(&flash)) { 50 | Serial.println("Error: filesystem is not existed. Please try SdFat_format " 51 | "example to make one."); 52 | while (1) { 53 | yield(); 54 | delay(1); 55 | } 56 | } 57 | 58 | Serial.println("initialization done."); 59 | 60 | // open the file. note that only one file can be open at a time, 61 | // so you have to close this one before opening another. 62 | myFile = fatfs.open("test.txt", FILE_WRITE); 63 | 64 | // if the file opened okay, write to it: 65 | if (myFile) { 66 | Serial.print("Writing to test.txt..."); 67 | myFile.println("testing 1, 2, 3."); 68 | // close the file: 69 | myFile.close(); 70 | Serial.println("done."); 71 | } else { 72 | // if the file didn't open, print an error: 73 | Serial.println("error opening test.txt"); 74 | } 75 | 76 | // re-open the file for reading: 77 | myFile = fatfs.open("test.txt"); 78 | if (myFile) { 79 | Serial.println("test.txt:"); 80 | 81 | // read from the file until there's nothing else in it: 82 | while (myFile.available()) { 83 | Serial.write(myFile.read()); 84 | } 85 | // close the file: 86 | myFile.close(); 87 | } else { 88 | // if the file didn't open, print an error: 89 | Serial.println("error opening test.txt"); 90 | } 91 | } 92 | 93 | void loop() { 94 | // nothing happens after setup 95 | } 96 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Report a problem 3 | labels: 'Bug' 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thanks for taking the time to fill out this bug report! 9 | It's okay to leave some blank if it doesn't apply to your problem. 10 | 11 | - type: dropdown 12 | attributes: 13 | label: Operating System 14 | options: 15 | - Linux 16 | - MacOS 17 | - RaspberryPi OS 18 | - Windows 7 19 | - Windows 10 20 | - Windows 11 21 | - Others 22 | validations: 23 | required: true 24 | 25 | - type: input 26 | attributes: 27 | label: IDE version 28 | placeholder: e.g Arduino 1.8.15 29 | validations: 30 | required: true 31 | 32 | - type: input 33 | attributes: 34 | label: Board 35 | placeholder: e.g Feather nRF52840 Express 36 | validations: 37 | required: true 38 | 39 | - type: input 40 | attributes: 41 | label: BSP version 42 | description: Can be found under "Board Manager" menu 43 | validations: 44 | required: true 45 | 46 | - type: input 47 | attributes: 48 | label: SPIFlash Library version 49 | placeholder: "Release version or github latest" 50 | validations: 51 | required: true 52 | 53 | - type: textarea 54 | attributes: 55 | label: Sketch as attached file if not stock example 56 | placeholder: | 57 | e.g examples/flash_info 58 | If it is custom sketch, please provide links to your minimal sources or as attached files. 59 | validations: 60 | required: true 61 | 62 | - type: textarea 63 | attributes: 64 | label: What happened ? 65 | placeholder: A clear and concise description of what the bug is. 66 | validations: 67 | required: true 68 | 69 | - type: textarea 70 | attributes: 71 | label: How to reproduce ? 72 | placeholder: | 73 | 1. Go to '...' 74 | 2. Click on '....' 75 | 3. See error 76 | validations: 77 | required: true 78 | 79 | - type: textarea 80 | attributes: 81 | label: Debug Log as attached txt file 82 | placeholder: | 83 | Debug log where the issue occurred as attached txt file, best with comments to explain the actual events. 84 | validations: 85 | required: false 86 | 87 | - type: textarea 88 | attributes: 89 | label: Screenshots 90 | description: If applicable, add screenshots to help explain your problem. 91 | validations: 92 | required: false 93 | -------------------------------------------------------------------------------- /src/spi/Adafruit_FlashTransport_SPI.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 hathach for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef ADAFRUIT_FLASHTRANSPORT_SPI_H_ 26 | #define ADAFRUIT_FLASHTRANSPORT_SPI_H_ 27 | 28 | #include "Arduino.h" 29 | #include "SPI.h" 30 | 31 | class Adafruit_FlashTransport_SPI : public Adafruit_FlashTransport { 32 | private: 33 | SPIClass *_spi; 34 | uint8_t _ss; 35 | 36 | // SAMD21 M0 can write up to 24 Mhz, but can only read reliably with 12 MHz 37 | uint32_t _clock_wr; 38 | uint32_t _clock_rd; 39 | 40 | public: 41 | Adafruit_FlashTransport_SPI(uint8_t ss, SPIClass *spiinterface); 42 | Adafruit_FlashTransport_SPI(uint8_t ss, SPIClass &spiinterface); 43 | 44 | virtual void begin(void); 45 | virtual void end(void); 46 | 47 | virtual bool supportQuadMode(void) { return false; } 48 | 49 | virtual void setClockSpeed(uint32_t write_hz, uint32_t read_hz); 50 | 51 | virtual bool runCommand(uint8_t command); 52 | virtual bool readCommand(uint8_t command, uint8_t *response, uint32_t len); 53 | virtual bool writeCommand(uint8_t command, uint8_t const *data, uint32_t len); 54 | virtual bool eraseCommand(uint8_t command, uint32_t addr); 55 | 56 | virtual bool readMemory(uint32_t addr, uint8_t *data, uint32_t len); 57 | virtual bool writeMemory(uint32_t addr, uint8_t const *data, uint32_t len); 58 | 59 | private: 60 | void fillAddress(uint8_t *buf, uint32_t addr); 61 | 62 | void beginTransaction(uint32_t clock_hz) { 63 | _spi->beginTransaction(SPISettings(clock_hz, MSBFIRST, SPI_MODE0)); 64 | digitalWrite(_ss, LOW); 65 | } 66 | 67 | void endTransaction(void) { 68 | digitalWrite(_ss, HIGH); 69 | _spi->endTransaction(); 70 | } 71 | }; 72 | 73 | #endif /* ADAFRUIT_FLASHTRANSPORT_SPI_H_ */ 74 | -------------------------------------------------------------------------------- /examples/SdFat_format/diskio.h: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------/ 2 | / Low level disk interface module include file (C)ChaN, 2014 / 3 | /-----------------------------------------------------------------------*/ 4 | 5 | #ifndef _DISKIO_DEFINED 6 | #define _DISKIO_DEFINED 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /* Status of Disk Functions */ 13 | typedef BYTE DSTATUS; 14 | 15 | /* Results of Disk Functions */ 16 | typedef enum { 17 | RES_OK = 0, /* 0: Successful */ 18 | RES_ERROR, /* 1: R/W Error */ 19 | RES_WRPRT, /* 2: Write Protected */ 20 | RES_NOTRDY, /* 3: Not Ready */ 21 | RES_PARERR /* 4: Invalid Parameter */ 22 | } DRESULT; 23 | 24 | 25 | /*---------------------------------------*/ 26 | /* Prototypes for disk control functions */ 27 | 28 | 29 | DSTATUS disk_initialize (BYTE pdrv); 30 | DSTATUS disk_status (BYTE pdrv); 31 | DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); 32 | DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); 33 | DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); 34 | 35 | 36 | /* Disk Status Bits (DSTATUS) */ 37 | 38 | #define STA_NOINIT 0x01 /* Drive not initialized */ 39 | #define STA_NODISK 0x02 /* No medium in the drive */ 40 | #define STA_PROTECT 0x04 /* Write protected */ 41 | 42 | 43 | /* Command code for disk_ioctrl function */ 44 | 45 | /* Generic command (Used by FatFs) */ 46 | #define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */ 47 | #define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */ 48 | #define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */ 49 | #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */ 50 | #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */ 51 | 52 | /* Generic command (Not used by FatFs) */ 53 | #define CTRL_POWER 5 /* Get/Set power status */ 54 | #define CTRL_LOCK 6 /* Lock/Unlock media removal */ 55 | #define CTRL_EJECT 7 /* Eject media */ 56 | #define CTRL_FORMAT 8 /* Create physical format on the media */ 57 | 58 | /* MMC/SDC specific ioctl command */ 59 | #define MMC_GET_TYPE 10 /* Get card type */ 60 | #define MMC_GET_CSD 11 /* Get CSD */ 61 | #define MMC_GET_CID 12 /* Get CID */ 62 | #define MMC_GET_OCR 13 /* Get OCR */ 63 | #define MMC_GET_SDSTAT 14 /* Get SD status */ 64 | #define ISDIO_READ 55 /* Read data form SD iSDIO register */ 65 | #define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ 66 | #define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ 67 | 68 | /* ATA/CF specific ioctl command */ 69 | #define ATA_GET_REV 20 /* Get F/W revision */ 70 | #define ATA_GET_MODEL 21 /* Get model name */ 71 | #define ATA_GET_SN 22 /* Get serial number */ 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /examples/flash_erase_express/flash_erase_express.ino: -------------------------------------------------------------------------------- 1 | // Adafruit SPI Flash Total Erase 2 | // Authors: Tony DiCola, Dan Halbert 3 | // 4 | // This example will perform a complete erase of ALL data on the SPI 5 | // flash. This is handy to reset the flash into a known empty state 6 | // and fix potential filesystem or other corruption issues. 7 | // 8 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 9 | // !! NOTE: YOU WILL ERASE ALL DATA BY RUNNING THIS SKETCH! !! 10 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 11 | // 12 | // Usage: 13 | // - Modify the pins and type of fatfs object in the config 14 | // section below if necessary (usually not necessary). 15 | // - Upload this sketch to your M0 express board. 16 | // - Upon starting the board Neopixel will be blue 17 | // - About 13 seconds later, the Neopixel should starting flashing 18 | // green once per second. This indicates the SPI flash has been 19 | // erased and all is well. 20 | // - If the Nexopixel starts flashing red two or three times a second, 21 | // an error has occurred. 22 | 23 | #include "SdFat_Adafruit_Fork.h" 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | // for flashTransport definition 30 | #include "flash_config.h" 31 | 32 | Adafruit_SPIFlash flash(&flashTransport); 33 | 34 | // On-board status Neopixel. 35 | #if defined(ARDUINO_TRELLIS_M4) 36 | #define PIN_NEOPIXEL 10 37 | #elif defined(ARDUINO_PYPORTAL_M4) || defined(ADAFRUIT_PYPORTAL_M4_TITANO) 38 | #define PIN_NEOPIXEL 2 39 | #elif defined(ADAFRUIT_PYBADGE_M4_EXPRESS) 40 | #define PIN_NEOPIXEL 8 41 | #else 42 | // something else? 43 | #warning "PIN_NEOPIXEL is not defined/detected, default to 8" 44 | #define PIN_NEOPIXEL 8 45 | #endif 46 | 47 | Adafruit_NeoPixel pixel = 48 | Adafruit_NeoPixel(1, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800); 49 | uint32_t BLUE = pixel.Color(0, 0, 100); 50 | uint32_t GREEN = pixel.Color(0, 100, 0); 51 | uint32_t YELLOW = pixel.Color(100, 100, 0); 52 | uint32_t RED = pixel.Color(100, 0, 0); 53 | uint32_t OFF = pixel.Color(0, 0, 0); 54 | 55 | void setup() { 56 | // Start with a blue pixel. 57 | pixel.begin(); 58 | pixel.setBrightness(30); 59 | pixel.setPixelColor(0, BLUE); 60 | pixel.show(); 61 | 62 | // Initialize flash library and check its chip ID. 63 | if (!flash.begin()) { 64 | // blink red 65 | blink(2, RED); 66 | } 67 | 68 | pixel.setPixelColor(0, YELLOW); 69 | pixel.show(); 70 | 71 | if (!flash.eraseChip()) { 72 | blink(3, RED); 73 | } 74 | 75 | flash.waitUntilReady(); 76 | blink(1, GREEN); 77 | } 78 | 79 | void loop() { 80 | // Nothing to do in the loop. 81 | delay(100); 82 | } 83 | 84 | void blink(int times, uint32_t color) { 85 | while (1) { 86 | for (int i = 0; i < times; i++) { 87 | pixel.setPixelColor(0, color); 88 | pixel.show(); 89 | delay(100); 90 | pixel.setPixelColor(0, OFF); 91 | pixel.show(); 92 | delay(100); 93 | } 94 | delay(1000); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /examples/flash_erase/flash_erase.ino: -------------------------------------------------------------------------------- 1 | // Adafruit SPI Flash Total Erase 2 | // Author: Tony DiCola 3 | // 4 | // This example will perform a complete erase of ALL data on the SPI 5 | // flash. This is handy to reset the flash into a known empty state 6 | // and fix potential filesystem or other corruption issues. 7 | // 8 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 9 | // !! NOTE: YOU WILL ERASE ALL DATA BY RUNNING THIS SKETCH! !! 10 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 11 | // 12 | // Usage: 13 | // - Modify the pins and type of fatfs object in the config 14 | // section below if necessary (usually not necessary). 15 | // - Upload this sketch to your M0 express board. 16 | // - Open the serial monitor at 115200 baud. You should see a 17 | // prompt to confirm formatting. If you don't see the prompt 18 | // close the serial monitor, press the board reset button, 19 | // wait a few seconds, then open the serial monitor again. 20 | // - Type OK and enter to confirm the format when prompted, 21 | // the flash chip will be erased. 22 | #include "SdFat_Adafruit_Fork.h" 23 | #include 24 | 25 | #include 26 | 27 | // for flashTransport definition 28 | #include "flash_config.h" 29 | 30 | Adafruit_SPIFlash flash(&flashTransport); 31 | 32 | void setup() { 33 | // Initialize serial port and wait for it to open before continuing. 34 | Serial.begin(115200); 35 | while (!Serial) { 36 | delay(100); 37 | } 38 | Serial.println("Adafruit SPI Flash Total Erase Example"); 39 | 40 | // Initialize flash library and check its chip ID. 41 | if (!flash.begin()) { 42 | Serial.println("Error, failed to initialize flash chip!"); 43 | while (1) { 44 | } 45 | } 46 | Serial.print("Flash chip JEDEC ID: 0x"); 47 | Serial.println(flash.getJEDECID(), HEX); 48 | 49 | // Wait for user to send OK to continue. 50 | // Increase timeout to print message less frequently. 51 | Serial.setTimeout(30000); 52 | do { 53 | Serial.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" 54 | "!!!!!!!!!!"); 55 | Serial.println("This sketch will ERASE ALL DATA on the flash chip!"); 56 | Serial.println("Type OK (all caps) and press enter to continue."); 57 | Serial.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" 58 | "!!!!!!!!!!"); 59 | } while (!Serial.find((char *)"OK")); 60 | 61 | Serial.println("Erasing flash chip in 10 seconds..."); 62 | Serial.println( 63 | "Note you will see stat and other debug output printed repeatedly."); 64 | Serial.println( 65 | "Let it run for ~30 seconds until the flash erase is finished."); 66 | Serial.println("An error or success message will be printed when complete."); 67 | 68 | if (!flash.eraseChip()) { 69 | Serial.println("Failed to erase chip!"); 70 | } 71 | 72 | flash.waitUntilReady(); 73 | Serial.println("Successfully erased chip!"); 74 | } 75 | 76 | void loop() { 77 | // Nothing to do in the loop. 78 | delay(100); 79 | } 80 | -------------------------------------------------------------------------------- /src/Adafruit_SPIFlashBase.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 Ha Thach and Dean Miller for Adafruit Industries LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef ADAFRUIT_SPIFLASHBASE_H_ 26 | #define ADAFRUIT_SPIFLASHBASE_H_ 27 | 28 | #include "Adafruit_FlashTransport.h" 29 | #include "flash_devices.h" 30 | 31 | // for debugging 32 | #define SPIFLASH_DEBUG 0 33 | 34 | // An easy to use interface for working with Flash memory. 35 | // 36 | // If you are managing allocation of the Flash space yourself, this is the 37 | // class to use as it take very little RAM. 38 | class Adafruit_SPIFlashBase { 39 | public: 40 | Adafruit_SPIFlashBase(); 41 | Adafruit_SPIFlashBase(Adafruit_FlashTransport *transport); 42 | ~Adafruit_SPIFlashBase() {} 43 | 44 | bool begin(SPIFlash_Device_t const *flash_devs = NULL, size_t count = 1); 45 | void end(void); 46 | 47 | void setIndicator(int pin, bool state_on = true); 48 | 49 | uint32_t numPages(void); 50 | uint16_t pageSize(void); 51 | 52 | uint32_t size(void); 53 | 54 | uint8_t readStatus(void); 55 | uint8_t readStatus2(void); 56 | void waitUntilReady(void); 57 | bool writeEnable(void); 58 | bool writeDisable(void); 59 | bool isReady(void); // both WIP and WREN are clear 60 | 61 | uint32_t getJEDECID(void); 62 | 63 | uint32_t readBuffer(uint32_t address, uint8_t *buffer, uint32_t len); 64 | uint32_t writeBuffer(uint32_t address, uint8_t const *buffer, uint32_t len); 65 | 66 | bool erasePage(uint32_t pageNumber); 67 | bool eraseSector(uint32_t sectorNumber); 68 | bool eraseBlock(uint32_t blockNumber); 69 | bool eraseChip(void); 70 | 71 | // Helper 72 | uint8_t read8(uint32_t addr); 73 | uint16_t read16(uint32_t addr); 74 | uint32_t read32(uint32_t addr); 75 | 76 | protected: 77 | Adafruit_FlashTransport *_trans; 78 | SPIFlash_Device_t const *_flash_dev; 79 | 80 | int _ind_pin; 81 | bool _ind_active; 82 | 83 | void _indicator_on(void) { 84 | if (_ind_pin >= 0) { 85 | digitalWrite(_ind_pin, _ind_active ? HIGH : LOW); 86 | } 87 | } 88 | 89 | void _indicator_off(void) { 90 | if (_ind_pin >= 0) { 91 | digitalWrite(_ind_pin, _ind_active ? LOW : HIGH); 92 | } 93 | } 94 | }; 95 | 96 | #endif /* ADAFRUIT_SPIFLASHBASE_H_ */ 97 | -------------------------------------------------------------------------------- /examples/SdFat_print_file/SdFat_print_file.ino: -------------------------------------------------------------------------------- 1 | // Adafruit SPI Flash FatFs Simple Datalogging Example 2 | // Author: Tony DiCola 3 | // 4 | // This is a simple example that opens a file and prints its 5 | // entire contents to the serial monitor. Note that 6 | // you MUST have a flash chip that's formatted with a flash 7 | // filesystem before running, and there should be some sort 8 | // of text file on it to open and read. See the fatfs_format 9 | // example to perform this formatting, and the fatfs_datalogging 10 | // example to write a simple text file. 11 | // 12 | // Usage: 13 | // - Modify the pins and type of fatfs object in the config 14 | // section below if necessary (usually not necessary). 15 | // - Upload this sketch to your M0 express board. 16 | // - Open the serial monitor at 115200 baud. You should see the 17 | // example start to run and messages printed to the monitor. 18 | // If you don't see anything close the serial monitor, press 19 | // the board reset button, wait a few seconds, then open the 20 | // serial monitor again. 21 | 22 | #include "SdFat_Adafruit_Fork.h" 23 | #include 24 | 25 | #include 26 | 27 | // for flashTransport definition 28 | #include "flash_config.h" 29 | 30 | Adafruit_SPIFlash flash(&flashTransport); 31 | 32 | // file system object from SdFat 33 | FatVolume fatfs; 34 | 35 | // Configuration for the file to open and read: 36 | #define FILE_NAME "test2.txt" 37 | 38 | void setup() { 39 | // Initialize serial port and wait for it to open before continuing. 40 | Serial.begin(115200); 41 | while (!Serial) { 42 | delay(100); 43 | } 44 | Serial.println("Adafruit SPI Flash FatFs Simple File Printing Example"); 45 | 46 | // Initialize flash library and check its chip ID. 47 | if (!flash.begin()) { 48 | Serial.println("Error, failed to initialize flash chip!"); 49 | while (1) { 50 | delay(1); 51 | } 52 | } 53 | Serial.print("Flash chip JEDEC ID: 0x"); 54 | Serial.println(flash.getJEDECID(), HEX); 55 | 56 | // First call begin to mount the filesystem. Check that it returns true 57 | // to make sure the filesystem was mounted. 58 | if (!fatfs.begin(&flash)) { 59 | Serial.println("Error, failed to mount newly formatted filesystem!"); 60 | Serial.println( 61 | "Was the flash chip formatted with the fatfs_format example?"); 62 | while (1) { 63 | delay(1); 64 | } 65 | } 66 | Serial.println("Mounted filesystem!"); 67 | 68 | // Open the file for reading and check that it was successfully opened. 69 | // The FILE_READ mode will open the file for reading. 70 | File32 dataFile = fatfs.open(FILE_NAME, FILE_READ); 71 | if (dataFile) { 72 | // File was opened, now print out data character by character until at the 73 | // end of the file. 74 | Serial.println("Opened file, printing contents below:"); 75 | while (dataFile.available()) { 76 | // Use the read function to read the next character. 77 | // You can alternatively use other functions like readUntil, readString, 78 | // etc. See the fatfs_full_usage example for more details. 79 | char c = dataFile.read(); 80 | Serial.print(c); 81 | } 82 | } else { 83 | Serial.print("Failed to open file \""); 84 | Serial.print(FILE_NAME); 85 | Serial.print("\" !! Does it exist?"); 86 | } 87 | } 88 | 89 | void loop() { 90 | // Nothing to do in main loop. 91 | delay(100); 92 | } 93 | -------------------------------------------------------------------------------- /examples/SdFat_datalogging/SdFat_datalogging.ino: -------------------------------------------------------------------------------- 1 | // Adafruit SPI Flash FatFs Simple Datalogging Example 2 | // Author: Tony DiCola 3 | // 4 | // This is a simple dataloging example using the SPI Flash 5 | // FatFs library. The example will open a file on the SPI 6 | // flash and append new lines of data every minute. Note that 7 | // you MUST have a flash chip that's formatted with a flash 8 | // filesystem before running. See the fatfs_format example 9 | // to perform this formatting. 10 | // 11 | // Usage: 12 | // - Modify the pins and type of fatfs object in the config 13 | // section below if necessary (usually not necessary). 14 | // - Upload this sketch to your M0 express board. 15 | // - Open the serial monitor at 115200 baud. You should see the 16 | // example print a message every minute when it writes a new 17 | // value to the data logging file. 18 | #include "SdFat_Adafruit_Fork.h" 19 | #include 20 | 21 | #include 22 | 23 | // for flashTransport definition 24 | #include "flash_config.h" 25 | 26 | Adafruit_SPIFlash flash(&flashTransport); 27 | 28 | // file system object from SdFat 29 | FatVolume fatfs; 30 | 31 | // Configuration for the datalogging file: 32 | #define FILE_NAME "data.csv" 33 | 34 | void setup() { 35 | // Initialize serial port and wait for it to open before continuing. 36 | Serial.begin(115200); 37 | while (!Serial) { 38 | delay(100); 39 | } 40 | Serial.println("Adafruit SPI Flash FatFs Simple Datalogging Example"); 41 | 42 | // Initialize flash library and check its chip ID. 43 | if (!flash.begin()) { 44 | Serial.println("Error, failed to initialize flash chip!"); 45 | while (1) { 46 | delay(1); 47 | } 48 | } 49 | Serial.print("Flash chip JEDEC ID: 0x"); 50 | Serial.println(flash.getJEDECID(), HEX); 51 | 52 | // First call begin to mount the filesystem. Check that it returns true 53 | // to make sure the filesystem was mounted. 54 | if (!fatfs.begin(&flash)) { 55 | Serial.println("Error, failed to mount newly formatted filesystem!"); 56 | Serial.println( 57 | "Was the flash chip formatted with the fatfs_format example?"); 58 | while (1) { 59 | delay(1); 60 | } 61 | } 62 | Serial.println("Mounted filesystem!"); 63 | 64 | Serial.println("Logging data every 60 seconds..."); 65 | } 66 | 67 | void loop() { 68 | // Open the datalogging file for writing. The FILE_WRITE mode will open 69 | // the file for appending, i.e. it will add new data to the end of the file. 70 | File32 dataFile = fatfs.open(FILE_NAME, FILE_WRITE); 71 | // Check that the file opened successfully and write a line to it. 72 | if (dataFile) { 73 | // Take a new data reading from a sensor, etc. For this example just 74 | // make up a random number. 75 | int reading = random(0, 100); 76 | // Write a line to the file. You can use all the same print functions 77 | // as if you're writing to the serial monitor. For example to write 78 | // two CSV (commas separated) values: 79 | dataFile.print("Sensor #1"); 80 | dataFile.print(","); 81 | dataFile.print(reading, DEC); 82 | dataFile.println(); 83 | // Finally close the file when done writing. This is smart to do to make 84 | // sure all the data is written to the file. 85 | dataFile.close(); 86 | Serial.println("Wrote new measurement to data file!"); 87 | } else { 88 | Serial.println("Failed to open data file for writing!"); 89 | } 90 | 91 | Serial.println("Trying again in 60 seconds..."); 92 | 93 | // Wait 60 seconds. 94 | delay(60000L); 95 | } 96 | -------------------------------------------------------------------------------- /examples/SdFat_format/flash_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022 Ha Thach (tinyusb.org) for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef FLASH_CONFIG_H_ 26 | #define FLASH_CONFIG_H_ 27 | 28 | // Un-comment to run example with custom SPI and SS e.g with FRAM breakout 29 | // #define CUSTOM_CS A5 30 | // #define CUSTOM_SPI SPI 31 | 32 | #if defined(CUSTOM_CS) && defined(CUSTOM_SPI) 33 | Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI); 34 | 35 | #elif defined(ARDUINO_ARCH_ESP32) 36 | // ESP32 use same flash device that store code for file system. 37 | // SPIFlash will parse partition.cvs to detect FATFS partition to use 38 | Adafruit_FlashTransport_ESP32 flashTransport; 39 | 40 | #elif defined(ARDUINO_ARCH_RP2040) 41 | // RP2040 use same flash device that store code for file system. Therefore we 42 | // only need to specify start address and size (no need SPI or SS) 43 | // By default (start=0, size=0), values that match file system setting in 44 | // 'Tools->Flash Size' menu selection will be used. 45 | Adafruit_FlashTransport_RP2040 flashTransport; 46 | 47 | // To be compatible with CircuitPython partition scheme (start_address = 1 MB, 48 | // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or 49 | // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the 50 | // following line: 51 | // Adafruit_FlashTransport_RP2040 52 | // flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR, 53 | // Adafruit_FlashTransport_RP2040::CPY_SIZE); 54 | // Adafruit_FlashTransport_RP2040_CPY flashTransport; 55 | #else 56 | 57 | // On-board external flash (QSPI or SPI) macros should already 58 | // defined in your board variant if supported 59 | // - EXTERNAL_FLASH_USE_QSPI 60 | // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI 61 | 62 | #if defined(EXTERNAL_FLASH_USE_QSPI) 63 | Adafruit_FlashTransport_QSPI flashTransport; 64 | 65 | #elif defined(EXTERNAL_FLASH_USE_SPI) 66 | Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, 67 | EXTERNAL_FLASH_USE_SPI); 68 | 69 | #elif defined(__AVR__) || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) 70 | 71 | // Circuit Playground Express built with Arduino SAMD instead of Adafruit SAMD core or AVR core 72 | // Use stand SPI/SS for avr port. 73 | // Note: For AVR, cache will be disable due to lack of memory. 74 | Adafruit_FlashTransport_SPI flashTransport(SS, SPI); 75 | 76 | #else 77 | #error No (Q)SPI flash are defined for your board ! 78 | #endif 79 | 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /examples/flash_erase/flash_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022 Ha Thach (tinyusb.org) for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef FLASH_CONFIG_H_ 26 | #define FLASH_CONFIG_H_ 27 | 28 | // Un-comment to run example with custom SPI and SS e.g with FRAM breakout 29 | // #define CUSTOM_CS A5 30 | // #define CUSTOM_SPI SPI 31 | 32 | #if defined(CUSTOM_CS) && defined(CUSTOM_SPI) 33 | Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI); 34 | 35 | #elif defined(ARDUINO_ARCH_ESP32) 36 | // ESP32 use same flash device that store code for file system. 37 | // SPIFlash will parse partition.cvs to detect FATFS partition to use 38 | Adafruit_FlashTransport_ESP32 flashTransport; 39 | 40 | #elif defined(ARDUINO_ARCH_RP2040) 41 | // RP2040 use same flash device that store code for file system. Therefore we 42 | // only need to specify start address and size (no need SPI or SS) 43 | // By default (start=0, size=0), values that match file system setting in 44 | // 'Tools->Flash Size' menu selection will be used. 45 | Adafruit_FlashTransport_RP2040 flashTransport; 46 | 47 | // To be compatible with CircuitPython partition scheme (start_address = 1 MB, 48 | // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or 49 | // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the 50 | // following line: 51 | // Adafruit_FlashTransport_RP2040 52 | // flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR, 53 | // Adafruit_FlashTransport_RP2040::CPY_SIZE); 54 | // Adafruit_FlashTransport_RP2040_CPY flashTransport; 55 | #else 56 | 57 | // On-board external flash (QSPI or SPI) macros should already 58 | // defined in your board variant if supported 59 | // - EXTERNAL_FLASH_USE_QSPI 60 | // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI 61 | 62 | #if defined(EXTERNAL_FLASH_USE_QSPI) 63 | Adafruit_FlashTransport_QSPI flashTransport; 64 | 65 | #elif defined(EXTERNAL_FLASH_USE_SPI) 66 | Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, 67 | EXTERNAL_FLASH_USE_SPI); 68 | 69 | #elif defined(__AVR__) || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) 70 | 71 | // Circuit Playground Express built with Arduino SAMD instead of Adafruit SAMD 72 | // core or AVR core Use stand SPI/SS for avr port. Note: For AVR, cache will be 73 | // disable due to lack of memory. 74 | Adafruit_FlashTransport_SPI flashTransport(SS, SPI); 75 | 76 | #else 77 | #error No (Q)SPI flash are defined for your board ! 78 | #endif 79 | 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /examples/flash_info/flash_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022 Ha Thach (tinyusb.org) for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef FLASH_CONFIG_H_ 26 | #define FLASH_CONFIG_H_ 27 | 28 | // Un-comment to run example with custom SPI and SS e.g with FRAM breakout 29 | // #define CUSTOM_CS A5 30 | // #define CUSTOM_SPI SPI 31 | 32 | #if defined(CUSTOM_CS) && defined(CUSTOM_SPI) 33 | Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI); 34 | 35 | #elif defined(ARDUINO_ARCH_ESP32) 36 | // ESP32 use same flash device that store code for file system. 37 | // SPIFlash will parse partition.cvs to detect FATFS partition to use 38 | Adafruit_FlashTransport_ESP32 flashTransport; 39 | 40 | #elif defined(ARDUINO_ARCH_RP2040) 41 | // RP2040 use same flash device that store code for file system. Therefore we 42 | // only need to specify start address and size (no need SPI or SS) 43 | // By default (start=0, size=0), values that match file system setting in 44 | // 'Tools->Flash Size' menu selection will be used. 45 | Adafruit_FlashTransport_RP2040 flashTransport; 46 | 47 | // To be compatible with CircuitPython partition scheme (start_address = 1 MB, 48 | // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or 49 | // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the 50 | // following line: 51 | // Adafruit_FlashTransport_RP2040 52 | // flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR, 53 | // Adafruit_FlashTransport_RP2040::CPY_SIZE); 54 | // Adafruit_FlashTransport_RP2040_CPY flashTransport; 55 | #else 56 | 57 | // On-board external flash (QSPI or SPI) macros should already 58 | // defined in your board variant if supported 59 | // - EXTERNAL_FLASH_USE_QSPI 60 | // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI 61 | 62 | #if defined(EXTERNAL_FLASH_USE_QSPI) 63 | Adafruit_FlashTransport_QSPI flashTransport; 64 | 65 | #elif defined(EXTERNAL_FLASH_USE_SPI) 66 | Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, 67 | EXTERNAL_FLASH_USE_SPI); 68 | 69 | #elif defined(__AVR__) || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) 70 | 71 | // Circuit Playground Express built with Arduino SAMD instead of Adafruit SAMD 72 | // core or AVR core Use stand SPI/SS for avr port. Note: For AVR, cache will be 73 | // disable due to lack of memory. 74 | Adafruit_FlashTransport_SPI flashTransport(SS, SPI); 75 | 76 | #else 77 | #error No (Q)SPI flash are defined for your board ! 78 | #endif 79 | 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /examples/SdFat_OpenNext/flash_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022 Ha Thach (tinyusb.org) for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef FLASH_CONFIG_H_ 26 | #define FLASH_CONFIG_H_ 27 | 28 | // Un-comment to run example with custom SPI and SS e.g with FRAM breakout 29 | // #define CUSTOM_CS A5 30 | // #define CUSTOM_SPI SPI 31 | 32 | #if defined(CUSTOM_CS) && defined(CUSTOM_SPI) 33 | Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI); 34 | 35 | #elif defined(ARDUINO_ARCH_ESP32) 36 | // ESP32 use same flash device that store code for file system. 37 | // SPIFlash will parse partition.cvs to detect FATFS partition to use 38 | Adafruit_FlashTransport_ESP32 flashTransport; 39 | 40 | #elif defined(ARDUINO_ARCH_RP2040) 41 | // RP2040 use same flash device that store code for file system. Therefore we 42 | // only need to specify start address and size (no need SPI or SS) 43 | // By default (start=0, size=0), values that match file system setting in 44 | // 'Tools->Flash Size' menu selection will be used. 45 | Adafruit_FlashTransport_RP2040 flashTransport; 46 | 47 | // To be compatible with CircuitPython partition scheme (start_address = 1 MB, 48 | // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or 49 | // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the 50 | // following line: 51 | // Adafruit_FlashTransport_RP2040 52 | // flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR, 53 | // Adafruit_FlashTransport_RP2040::CPY_SIZE); 54 | // Adafruit_FlashTransport_RP2040_CPY flashTransport; 55 | #else 56 | 57 | // On-board external flash (QSPI or SPI) macros should already 58 | // defined in your board variant if supported 59 | // - EXTERNAL_FLASH_USE_QSPI 60 | // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI 61 | 62 | #if defined(EXTERNAL_FLASH_USE_QSPI) 63 | Adafruit_FlashTransport_QSPI flashTransport; 64 | 65 | #elif defined(EXTERNAL_FLASH_USE_SPI) 66 | Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, 67 | EXTERNAL_FLASH_USE_SPI); 68 | 69 | #elif defined(__AVR__) || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) 70 | 71 | // Circuit Playground Express built with Arduino SAMD instead of Adafruit SAMD 72 | // core or AVR core Use stand SPI/SS for avr port. Note: For AVR, cache will be 73 | // disable due to lack of memory. 74 | Adafruit_FlashTransport_SPI flashTransport(SS, SPI); 75 | 76 | #else 77 | #error No (Q)SPI flash are defined for your board ! 78 | #endif 79 | 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /examples/SdFat_ReadWrite/flash_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022 Ha Thach (tinyusb.org) for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef FLASH_CONFIG_H_ 26 | #define FLASH_CONFIG_H_ 27 | 28 | // Un-comment to run example with custom SPI and SS e.g with FRAM breakout 29 | // #define CUSTOM_CS A5 30 | // #define CUSTOM_SPI SPI 31 | 32 | #if defined(CUSTOM_CS) && defined(CUSTOM_SPI) 33 | Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI); 34 | 35 | #elif defined(ARDUINO_ARCH_ESP32) 36 | // ESP32 use same flash device that store code for file system. 37 | // SPIFlash will parse partition.cvs to detect FATFS partition to use 38 | Adafruit_FlashTransport_ESP32 flashTransport; 39 | 40 | #elif defined(ARDUINO_ARCH_RP2040) 41 | // RP2040 use same flash device that store code for file system. Therefore we 42 | // only need to specify start address and size (no need SPI or SS) 43 | // By default (start=0, size=0), values that match file system setting in 44 | // 'Tools->Flash Size' menu selection will be used. 45 | Adafruit_FlashTransport_RP2040 flashTransport; 46 | 47 | // To be compatible with CircuitPython partition scheme (start_address = 1 MB, 48 | // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or 49 | // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the 50 | // following line: 51 | // Adafruit_FlashTransport_RP2040 52 | // flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR, 53 | // Adafruit_FlashTransport_RP2040::CPY_SIZE); 54 | // Adafruit_FlashTransport_RP2040_CPY flashTransport; 55 | #else 56 | 57 | // On-board external flash (QSPI or SPI) macros should already 58 | // defined in your board variant if supported 59 | // - EXTERNAL_FLASH_USE_QSPI 60 | // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI 61 | 62 | #if defined(EXTERNAL_FLASH_USE_QSPI) 63 | Adafruit_FlashTransport_QSPI flashTransport; 64 | 65 | #elif defined(EXTERNAL_FLASH_USE_SPI) 66 | Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, 67 | EXTERNAL_FLASH_USE_SPI); 68 | 69 | #elif defined(__AVR__) || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) 70 | 71 | // Circuit Playground Express built with Arduino SAMD instead of Adafruit SAMD 72 | // core or AVR core Use stand SPI/SS for avr port. Note: For AVR, cache will be 73 | // disable due to lack of memory. 74 | Adafruit_FlashTransport_SPI flashTransport(SS, SPI); 75 | 76 | #else 77 | #error No (Q)SPI flash are defined for your board ! 78 | #endif 79 | 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /examples/SdFat_datalogging/flash_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022 Ha Thach (tinyusb.org) for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef FLASH_CONFIG_H_ 26 | #define FLASH_CONFIG_H_ 27 | 28 | // Un-comment to run example with custom SPI and SS e.g with FRAM breakout 29 | // #define CUSTOM_CS A5 30 | // #define CUSTOM_SPI SPI 31 | 32 | #if defined(CUSTOM_CS) && defined(CUSTOM_SPI) 33 | Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI); 34 | 35 | #elif defined(ARDUINO_ARCH_ESP32) 36 | // ESP32 use same flash device that store code for file system. 37 | // SPIFlash will parse partition.cvs to detect FATFS partition to use 38 | Adafruit_FlashTransport_ESP32 flashTransport; 39 | 40 | #elif defined(ARDUINO_ARCH_RP2040) 41 | // RP2040 use same flash device that store code for file system. Therefore we 42 | // only need to specify start address and size (no need SPI or SS) 43 | // By default (start=0, size=0), values that match file system setting in 44 | // 'Tools->Flash Size' menu selection will be used. 45 | Adafruit_FlashTransport_RP2040 flashTransport; 46 | 47 | // To be compatible with CircuitPython partition scheme (start_address = 1 MB, 48 | // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or 49 | // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the 50 | // following line: 51 | // Adafruit_FlashTransport_RP2040 52 | // flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR, 53 | // Adafruit_FlashTransport_RP2040::CPY_SIZE); 54 | // Adafruit_FlashTransport_RP2040_CPY flashTransport; 55 | #else 56 | 57 | // On-board external flash (QSPI or SPI) macros should already 58 | // defined in your board variant if supported 59 | // - EXTERNAL_FLASH_USE_QSPI 60 | // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI 61 | 62 | #if defined(EXTERNAL_FLASH_USE_QSPI) 63 | Adafruit_FlashTransport_QSPI flashTransport; 64 | 65 | #elif defined(EXTERNAL_FLASH_USE_SPI) 66 | Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, 67 | EXTERNAL_FLASH_USE_SPI); 68 | 69 | #elif defined(__AVR__) || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) 70 | 71 | // Circuit Playground Express built with Arduino SAMD instead of Adafruit SAMD 72 | // core or AVR core Use stand SPI/SS for avr port. Note: For AVR, cache will be 73 | // disable due to lack of memory. 74 | Adafruit_FlashTransport_SPI flashTransport(SS, SPI); 75 | 76 | #else 77 | #error No (Q)SPI flash are defined for your board ! 78 | #endif 79 | 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /examples/SdFat_full_usage/flash_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022 Ha Thach (tinyusb.org) for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef FLASH_CONFIG_H_ 26 | #define FLASH_CONFIG_H_ 27 | 28 | // Un-comment to run example with custom SPI and SS e.g with FRAM breakout 29 | // #define CUSTOM_CS A5 30 | // #define CUSTOM_SPI SPI 31 | 32 | #if defined(CUSTOM_CS) && defined(CUSTOM_SPI) 33 | Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI); 34 | 35 | #elif defined(ARDUINO_ARCH_ESP32) 36 | // ESP32 use same flash device that store code for file system. 37 | // SPIFlash will parse partition.cvs to detect FATFS partition to use 38 | Adafruit_FlashTransport_ESP32 flashTransport; 39 | 40 | #elif defined(ARDUINO_ARCH_RP2040) 41 | // RP2040 use same flash device that store code for file system. Therefore we 42 | // only need to specify start address and size (no need SPI or SS) 43 | // By default (start=0, size=0), values that match file system setting in 44 | // 'Tools->Flash Size' menu selection will be used. 45 | Adafruit_FlashTransport_RP2040 flashTransport; 46 | 47 | // To be compatible with CircuitPython partition scheme (start_address = 1 MB, 48 | // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or 49 | // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the 50 | // following line: 51 | // Adafruit_FlashTransport_RP2040 52 | // flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR, 53 | // Adafruit_FlashTransport_RP2040::CPY_SIZE); 54 | // Adafruit_FlashTransport_RP2040_CPY flashTransport; 55 | #else 56 | 57 | // On-board external flash (QSPI or SPI) macros should already 58 | // defined in your board variant if supported 59 | // - EXTERNAL_FLASH_USE_QSPI 60 | // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI 61 | 62 | #if defined(EXTERNAL_FLASH_USE_QSPI) 63 | Adafruit_FlashTransport_QSPI flashTransport; 64 | 65 | #elif defined(EXTERNAL_FLASH_USE_SPI) 66 | Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, 67 | EXTERNAL_FLASH_USE_SPI); 68 | 69 | #elif defined(__AVR__) || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) 70 | 71 | // Circuit Playground Express built with Arduino SAMD instead of Adafruit SAMD 72 | // core or AVR core Use stand SPI/SS for avr port. Note: For AVR, cache will be 73 | // disable due to lack of memory. 74 | Adafruit_FlashTransport_SPI flashTransport(SS, SPI); 75 | 76 | #else 77 | #error No (Q)SPI flash are defined for your board ! 78 | #endif 79 | 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /examples/SdFat_print_file/flash_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022 Ha Thach (tinyusb.org) for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef FLASH_CONFIG_H_ 26 | #define FLASH_CONFIG_H_ 27 | 28 | // Un-comment to run example with custom SPI and SS e.g with FRAM breakout 29 | // #define CUSTOM_CS A5 30 | // #define CUSTOM_SPI SPI 31 | 32 | #if defined(CUSTOM_CS) && defined(CUSTOM_SPI) 33 | Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI); 34 | 35 | #elif defined(ARDUINO_ARCH_ESP32) 36 | // ESP32 use same flash device that store code for file system. 37 | // SPIFlash will parse partition.cvs to detect FATFS partition to use 38 | Adafruit_FlashTransport_ESP32 flashTransport; 39 | 40 | #elif defined(ARDUINO_ARCH_RP2040) 41 | // RP2040 use same flash device that store code for file system. Therefore we 42 | // only need to specify start address and size (no need SPI or SS) 43 | // By default (start=0, size=0), values that match file system setting in 44 | // 'Tools->Flash Size' menu selection will be used. 45 | Adafruit_FlashTransport_RP2040 flashTransport; 46 | 47 | // To be compatible with CircuitPython partition scheme (start_address = 1 MB, 48 | // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or 49 | // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the 50 | // following line: 51 | // Adafruit_FlashTransport_RP2040 52 | // flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR, 53 | // Adafruit_FlashTransport_RP2040::CPY_SIZE); 54 | // Adafruit_FlashTransport_RP2040_CPY flashTransport; 55 | #else 56 | 57 | // On-board external flash (QSPI or SPI) macros should already 58 | // defined in your board variant if supported 59 | // - EXTERNAL_FLASH_USE_QSPI 60 | // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI 61 | 62 | #if defined(EXTERNAL_FLASH_USE_QSPI) 63 | Adafruit_FlashTransport_QSPI flashTransport; 64 | 65 | #elif defined(EXTERNAL_FLASH_USE_SPI) 66 | Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, 67 | EXTERNAL_FLASH_USE_SPI); 68 | 69 | #elif defined(__AVR__) || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) 70 | 71 | // Circuit Playground Express built with Arduino SAMD instead of Adafruit SAMD 72 | // core or AVR core Use stand SPI/SS for avr port. Note: For AVR, cache will be 73 | // disable due to lack of memory. 74 | Adafruit_FlashTransport_SPI flashTransport(SS, SPI); 75 | 76 | #else 77 | #error No (Q)SPI flash are defined for your board ! 78 | #endif 79 | 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /examples/flash_manipulator/flash_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022 Ha Thach (tinyusb.org) for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef FLASH_CONFIG_H_ 26 | #define FLASH_CONFIG_H_ 27 | 28 | // Un-comment to run example with custom SPI and SS e.g with FRAM breakout 29 | // #define CUSTOM_CS A5 30 | // #define CUSTOM_SPI SPI 31 | 32 | #if defined(CUSTOM_CS) && defined(CUSTOM_SPI) 33 | Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI); 34 | 35 | #elif defined(ARDUINO_ARCH_ESP32) 36 | // ESP32 use same flash device that store code for file system. 37 | // SPIFlash will parse partition.cvs to detect FATFS partition to use 38 | Adafruit_FlashTransport_ESP32 flashTransport; 39 | 40 | #elif defined(ARDUINO_ARCH_RP2040) 41 | // RP2040 use same flash device that store code for file system. Therefore we 42 | // only need to specify start address and size (no need SPI or SS) 43 | // By default (start=0, size=0), values that match file system setting in 44 | // 'Tools->Flash Size' menu selection will be used. 45 | Adafruit_FlashTransport_RP2040 flashTransport; 46 | 47 | // To be compatible with CircuitPython partition scheme (start_address = 1 MB, 48 | // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or 49 | // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the 50 | // following line: 51 | // Adafruit_FlashTransport_RP2040 52 | // flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR, 53 | // Adafruit_FlashTransport_RP2040::CPY_SIZE); 54 | // Adafruit_FlashTransport_RP2040_CPY flashTransport; 55 | #else 56 | 57 | // On-board external flash (QSPI or SPI) macros should already 58 | // defined in your board variant if supported 59 | // - EXTERNAL_FLASH_USE_QSPI 60 | // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI 61 | 62 | #if defined(EXTERNAL_FLASH_USE_QSPI) 63 | Adafruit_FlashTransport_QSPI flashTransport; 64 | 65 | #elif defined(EXTERNAL_FLASH_USE_SPI) 66 | Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, 67 | EXTERNAL_FLASH_USE_SPI); 68 | 69 | #elif defined(__AVR__) || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) 70 | 71 | // Circuit Playground Express built with Arduino SAMD instead of Adafruit SAMD 72 | // core or AVR core Use stand SPI/SS for avr port. Note: For AVR, cache will be 73 | // disable due to lack of memory. 74 | Adafruit_FlashTransport_SPI flashTransport(SS, SPI); 75 | 76 | #else 77 | #error No (Q)SPI flash are defined for your board ! 78 | #endif 79 | 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /examples/flash_sector_dump/flash_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022 Ha Thach (tinyusb.org) for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef FLASH_CONFIG_H_ 26 | #define FLASH_CONFIG_H_ 27 | 28 | // Un-comment to run example with custom SPI and SS e.g with FRAM breakout 29 | // #define CUSTOM_CS A5 30 | // #define CUSTOM_SPI SPI 31 | 32 | #if defined(CUSTOM_CS) && defined(CUSTOM_SPI) 33 | Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI); 34 | 35 | #elif defined(ARDUINO_ARCH_ESP32) 36 | // ESP32 use same flash device that store code for file system. 37 | // SPIFlash will parse partition.cvs to detect FATFS partition to use 38 | Adafruit_FlashTransport_ESP32 flashTransport; 39 | 40 | #elif defined(ARDUINO_ARCH_RP2040) 41 | // RP2040 use same flash device that store code for file system. Therefore we 42 | // only need to specify start address and size (no need SPI or SS) 43 | // By default (start=0, size=0), values that match file system setting in 44 | // 'Tools->Flash Size' menu selection will be used. 45 | Adafruit_FlashTransport_RP2040 flashTransport; 46 | 47 | // To be compatible with CircuitPython partition scheme (start_address = 1 MB, 48 | // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or 49 | // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the 50 | // following line: 51 | // Adafruit_FlashTransport_RP2040 52 | // flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR, 53 | // Adafruit_FlashTransport_RP2040::CPY_SIZE); 54 | // Adafruit_FlashTransport_RP2040_CPY flashTransport; 55 | #else 56 | 57 | // On-board external flash (QSPI or SPI) macros should already 58 | // defined in your board variant if supported 59 | // - EXTERNAL_FLASH_USE_QSPI 60 | // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI 61 | 62 | #if defined(EXTERNAL_FLASH_USE_QSPI) 63 | Adafruit_FlashTransport_QSPI flashTransport; 64 | 65 | #elif defined(EXTERNAL_FLASH_USE_SPI) 66 | Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, 67 | EXTERNAL_FLASH_USE_SPI); 68 | 69 | #elif defined(__AVR__) || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) 70 | 71 | // Circuit Playground Express built with Arduino SAMD instead of Adafruit SAMD 72 | // core or AVR core Use stand SPI/SS for avr port. Note: For AVR, cache will be 73 | // disable due to lack of memory. 74 | Adafruit_FlashTransport_SPI flashTransport(SS, SPI); 75 | 76 | #else 77 | #error No (Q)SPI flash are defined for your board ! 78 | #endif 79 | 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /examples/flash_speedtest/flash_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022 Ha Thach (tinyusb.org) for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef FLASH_CONFIG_H_ 26 | #define FLASH_CONFIG_H_ 27 | 28 | // Un-comment to run example with custom SPI and SS e.g with FRAM breakout 29 | // #define CUSTOM_CS A5 30 | // #define CUSTOM_SPI SPI 31 | 32 | #if defined(CUSTOM_CS) && defined(CUSTOM_SPI) 33 | Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI); 34 | 35 | #elif defined(ARDUINO_ARCH_ESP32) 36 | // ESP32 use same flash device that store code for file system. 37 | // SPIFlash will parse partition.cvs to detect FATFS partition to use 38 | Adafruit_FlashTransport_ESP32 flashTransport; 39 | 40 | #elif defined(ARDUINO_ARCH_RP2040) 41 | // RP2040 use same flash device that store code for file system. Therefore we 42 | // only need to specify start address and size (no need SPI or SS) 43 | // By default (start=0, size=0), values that match file system setting in 44 | // 'Tools->Flash Size' menu selection will be used. 45 | Adafruit_FlashTransport_RP2040 flashTransport; 46 | 47 | // To be compatible with CircuitPython partition scheme (start_address = 1 MB, 48 | // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or 49 | // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the 50 | // following line: 51 | // Adafruit_FlashTransport_RP2040 52 | // flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR, 53 | // Adafruit_FlashTransport_RP2040::CPY_SIZE); 54 | // Adafruit_FlashTransport_RP2040_CPY flashTransport; 55 | #else 56 | 57 | // On-board external flash (QSPI or SPI) macros should already 58 | // defined in your board variant if supported 59 | // - EXTERNAL_FLASH_USE_QSPI 60 | // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI 61 | 62 | #if defined(EXTERNAL_FLASH_USE_QSPI) 63 | Adafruit_FlashTransport_QSPI flashTransport; 64 | 65 | #elif defined(EXTERNAL_FLASH_USE_SPI) 66 | Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, 67 | EXTERNAL_FLASH_USE_SPI); 68 | 69 | #elif defined(__AVR__) || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) 70 | 71 | // Circuit Playground Express built with Arduino SAMD instead of Adafruit SAMD 72 | // core or AVR core Use stand SPI/SS for avr port. Note: For AVR, cache will be 73 | // disable due to lack of memory. 74 | Adafruit_FlashTransport_SPI flashTransport(SS, SPI); 75 | 76 | #else 77 | #error No (Q)SPI flash are defined for your board ! 78 | #endif 79 | 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /examples/SdFat_Flash_and_SDcard/flash_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022 Ha Thach (tinyusb.org) for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef FLASH_CONFIG_H_ 26 | #define FLASH_CONFIG_H_ 27 | 28 | // Un-comment to run example with custom SPI and SS e.g with FRAM breakout 29 | // #define CUSTOM_CS A5 30 | // #define CUSTOM_SPI SPI 31 | 32 | #if defined(CUSTOM_CS) && defined(CUSTOM_SPI) 33 | Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI); 34 | 35 | #elif defined(ARDUINO_ARCH_ESP32) 36 | // ESP32 use same flash device that store code for file system. 37 | // SPIFlash will parse partition.cvs to detect FATFS partition to use 38 | Adafruit_FlashTransport_ESP32 flashTransport; 39 | 40 | #elif defined(ARDUINO_ARCH_RP2040) 41 | // RP2040 use same flash device that store code for file system. Therefore we 42 | // only need to specify start address and size (no need SPI or SS) 43 | // By default (start=0, size=0), values that match file system setting in 44 | // 'Tools->Flash Size' menu selection will be used. 45 | Adafruit_FlashTransport_RP2040 flashTransport; 46 | 47 | // To be compatible with CircuitPython partition scheme (start_address = 1 MB, 48 | // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or 49 | // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the 50 | // following line: 51 | // Adafruit_FlashTransport_RP2040 52 | // flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR, 53 | // Adafruit_FlashTransport_RP2040::CPY_SIZE); 54 | // Adafruit_FlashTransport_RP2040_CPY flashTransport; 55 | #else 56 | 57 | // On-board external flash (QSPI or SPI) macros should already 58 | // defined in your board variant if supported 59 | // - EXTERNAL_FLASH_USE_QSPI 60 | // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI 61 | 62 | #if defined(EXTERNAL_FLASH_USE_QSPI) 63 | Adafruit_FlashTransport_QSPI flashTransport; 64 | 65 | #elif defined(EXTERNAL_FLASH_USE_SPI) 66 | Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, 67 | EXTERNAL_FLASH_USE_SPI); 68 | 69 | #elif defined(__AVR__) || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) 70 | 71 | // Circuit Playground Express built with Arduino SAMD instead of Adafruit SAMD 72 | // core or AVR core Use stand SPI/SS for avr port. Note: For AVR, cache will be 73 | // disable due to lack of memory. 74 | Adafruit_FlashTransport_SPI flashTransport(SS, SPI); 75 | 76 | #else 77 | #error No (Q)SPI flash are defined for your board ! 78 | #endif 79 | 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /examples/SdFat_circuitpython/flash_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022 Ha Thach (tinyusb.org) for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef FLASH_CONFIG_H_ 26 | #define FLASH_CONFIG_H_ 27 | 28 | // Un-comment to run example with custom SPI and SS e.g with FRAM breakout 29 | // #define CUSTOM_CS A5 30 | // #define CUSTOM_SPI SPI 31 | 32 | #if defined(CUSTOM_CS) && defined(CUSTOM_SPI) 33 | Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI); 34 | 35 | #elif defined(ARDUINO_ARCH_ESP32) 36 | // ESP32 use same flash device that store code for file system. 37 | // SPIFlash will parse partition.cvs to detect FATFS partition to use 38 | Adafruit_FlashTransport_ESP32 flashTransport; 39 | 40 | #elif defined(ARDUINO_ARCH_RP2040) 41 | // RP2040 use same flash device that store code for file system. Therefore we 42 | // only need to specify start address and size (no need SPI or SS) 43 | // By default (start=0, size=0), values that match file system setting in 44 | // 'Tools->Flash Size' menu selection will be used. 45 | Adafruit_FlashTransport_RP2040 flashTransport; 46 | 47 | // To be compatible with CircuitPython partition scheme (start_address = 1 MB, 48 | // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or 49 | // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the 50 | // following line: 51 | // Adafruit_FlashTransport_RP2040 52 | // flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR, 53 | // Adafruit_FlashTransport_RP2040::CPY_SIZE); 54 | // Adafruit_FlashTransport_RP2040_CPY flashTransport; 55 | #else 56 | 57 | // On-board external flash (QSPI or SPI) macros should already 58 | // defined in your board variant if supported 59 | // - EXTERNAL_FLASH_USE_QSPI 60 | // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI 61 | 62 | #if defined(EXTERNAL_FLASH_USE_QSPI) 63 | Adafruit_FlashTransport_QSPI flashTransport; 64 | 65 | #elif defined(EXTERNAL_FLASH_USE_SPI) 66 | Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, 67 | EXTERNAL_FLASH_USE_SPI); 68 | 69 | #elif defined(__AVR__) || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) 70 | 71 | // Circuit Playground Express built with Arduino SAMD instead of Adafruit SAMD 72 | // core or AVR core Use stand SPI/SS for avr port. Note: For AVR, cache will be 73 | // disable due to lack of memory. 74 | Adafruit_FlashTransport_SPI flashTransport(SS, SPI); 75 | 76 | #else 77 | #error No (Q)SPI flash are defined for your board ! 78 | #endif 79 | 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /examples/flash_erase_express/flash_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022 Ha Thach (tinyusb.org) for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef FLASH_CONFIG_H_ 26 | #define FLASH_CONFIG_H_ 27 | 28 | // Un-comment to run example with custom SPI and SS e.g with FRAM breakout 29 | // #define CUSTOM_CS A5 30 | // #define CUSTOM_SPI SPI 31 | 32 | #if defined(CUSTOM_CS) && defined(CUSTOM_SPI) 33 | Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI); 34 | 35 | #elif defined(ARDUINO_ARCH_ESP32) 36 | // ESP32 use same flash device that store code for file system. 37 | // SPIFlash will parse partition.cvs to detect FATFS partition to use 38 | Adafruit_FlashTransport_ESP32 flashTransport; 39 | 40 | #elif defined(ARDUINO_ARCH_RP2040) 41 | // RP2040 use same flash device that store code for file system. Therefore we 42 | // only need to specify start address and size (no need SPI or SS) 43 | // By default (start=0, size=0), values that match file system setting in 44 | // 'Tools->Flash Size' menu selection will be used. 45 | Adafruit_FlashTransport_RP2040 flashTransport; 46 | 47 | // To be compatible with CircuitPython partition scheme (start_address = 1 MB, 48 | // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or 49 | // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the 50 | // following line: 51 | // Adafruit_FlashTransport_RP2040 52 | // flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR, 53 | // Adafruit_FlashTransport_RP2040::CPY_SIZE); 54 | // Adafruit_FlashTransport_RP2040_CPY flashTransport; 55 | #else 56 | 57 | // On-board external flash (QSPI or SPI) macros should already 58 | // defined in your board variant if supported 59 | // - EXTERNAL_FLASH_USE_QSPI 60 | // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI 61 | 62 | #if defined(EXTERNAL_FLASH_USE_QSPI) 63 | Adafruit_FlashTransport_QSPI flashTransport; 64 | 65 | #elif defined(EXTERNAL_FLASH_USE_SPI) 66 | Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, 67 | EXTERNAL_FLASH_USE_SPI); 68 | 69 | #elif defined(__AVR__) || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) 70 | 71 | // Circuit Playground Express built with Arduino SAMD instead of Adafruit SAMD 72 | // core or AVR core Use stand SPI/SS for avr port. Note: For AVR, cache will be 73 | // disable due to lack of memory. 74 | Adafruit_FlashTransport_SPI flashTransport(SS, SPI); 75 | 76 | #else 77 | #error No (Q)SPI flash are defined for your board ! 78 | #endif 79 | 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /examples/SdFat_circuitpython_backupFiles/flash_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022 Ha Thach (tinyusb.org) for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef FLASH_CONFIG_H_ 26 | #define FLASH_CONFIG_H_ 27 | 28 | // Un-comment to run example with custom SPI and SS e.g with FRAM breakout 29 | // #define CUSTOM_CS A5 30 | // #define CUSTOM_SPI SPI 31 | 32 | #if defined(CUSTOM_CS) && defined(CUSTOM_SPI) 33 | Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI); 34 | 35 | #elif defined(ARDUINO_ARCH_ESP32) 36 | // ESP32 use same flash device that store code for file system. 37 | // SPIFlash will parse partition.cvs to detect FATFS partition to use 38 | Adafruit_FlashTransport_ESP32 flashTransport; 39 | 40 | #elif defined(ARDUINO_ARCH_RP2040) 41 | // RP2040 use same flash device that store code for file system. Therefore we 42 | // only need to specify start address and size (no need SPI or SS) 43 | // By default (start=0, size=0), values that match file system setting in 44 | // 'Tools->Flash Size' menu selection will be used. 45 | Adafruit_FlashTransport_RP2040 flashTransport; 46 | 47 | // To be compatible with CircuitPython partition scheme (start_address = 1 MB, 48 | // size = total flash - 1 MB) use const value (CPY_START_ADDR, CPY_SIZE) or 49 | // subclass Adafruit_FlashTransport_RP2040_CPY. Un-comment either of the 50 | // following line: 51 | // Adafruit_FlashTransport_RP2040 52 | // flashTransport(Adafruit_FlashTransport_RP2040::CPY_START_ADDR, 53 | // Adafruit_FlashTransport_RP2040::CPY_SIZE); 54 | // Adafruit_FlashTransport_RP2040_CPY flashTransport; 55 | #else 56 | 57 | // On-board external flash (QSPI or SPI) macros should already 58 | // defined in your board variant if supported 59 | // - EXTERNAL_FLASH_USE_QSPI 60 | // - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI 61 | 62 | #if defined(EXTERNAL_FLASH_USE_QSPI) 63 | Adafruit_FlashTransport_QSPI flashTransport; 64 | 65 | #elif defined(EXTERNAL_FLASH_USE_SPI) 66 | Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, 67 | EXTERNAL_FLASH_USE_SPI); 68 | 69 | #elif defined(__AVR__) || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) 70 | 71 | // Circuit Playground Express built with Arduino SAMD instead of Adafruit SAMD 72 | // core or AVR core Use stand SPI/SS for avr port. Note: For AVR, cache will be 73 | // disable due to lack of memory. 74 | Adafruit_FlashTransport_SPI flashTransport(SS, SPI); 75 | 76 | #else 77 | #error No (Q)SPI flash are defined for your board ! 78 | #endif 79 | 80 | #endif 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /src/rp2040/Adafruit_FlashTransport_RP2040.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2020 hathach for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef ADAFRUIT_FLASHTRANSPORT_RP2040_H_ 26 | #define ADAFRUIT_FLASHTRANSPORT_RP2040_H_ 27 | 28 | #include "Arduino.h" 29 | #include "SPI.h" 30 | #include "flash_devices.h" 31 | 32 | class Adafruit_FlashTransport_RP2040 : public Adafruit_FlashTransport { 33 | protected: 34 | uint32_t _start_addr; 35 | uint32_t _size; 36 | SPIFlash_Device_t _flash_dev; 37 | 38 | // check if relative addr is valid 39 | bool check_addr(uint32_t addr) { return addr <= _size; } 40 | 41 | // Flag (set via constructor) indicates whether other core must pause when 42 | // writing or erasing flash. Default state is true, pause other core. VERY 43 | // rare that this needs changed, REQUIRES SPECIAL LINKER CONFIG to locate 44 | // ALL functions of other core entirely in RAM, else hard crash and flash 45 | // filesystem corruption. PicoDVI is a rare use case. 46 | bool _idle_other_core_on_write; 47 | 48 | public: 49 | static const uint32_t CPY_START_ADDR; 50 | static const uint32_t CPY_SIZE; 51 | 52 | // Generic constructor with address and size. If start_address and size are 0, 53 | // value that matches filesystem setting in 'Tools->Flash Size' menu selection 54 | // will be used. 55 | // 56 | // To be compatible with CircuitPython partition scheme (start_address = 1 57 | // MB, size = total flash - 1 MB) use 58 | // Adafruit_FlashTransport_RP2040(CPY_START_ADDR, CPY_SIZE) 59 | Adafruit_FlashTransport_RP2040(uint32_t start_addr = 0, uint32_t size = 0, 60 | bool idle = true); 61 | 62 | virtual void begin(void); 63 | virtual void end(void); 64 | 65 | virtual bool supportQuadMode(void) { return false; } 66 | 67 | virtual void setClockSpeed(uint32_t write_hz, uint32_t read_hz); 68 | 69 | virtual bool runCommand(uint8_t command); 70 | virtual bool readCommand(uint8_t command, uint8_t *response, uint32_t len); 71 | virtual bool writeCommand(uint8_t command, uint8_t const *data, uint32_t len); 72 | virtual bool eraseCommand(uint8_t command, uint32_t addr); 73 | 74 | virtual bool readMemory(uint32_t addr, uint8_t *data, uint32_t len); 75 | virtual bool writeMemory(uint32_t addr, uint8_t const *data, uint32_t len); 76 | 77 | // Flash device is already detected and configured, get the pointer without 78 | // go through initial sequence 79 | SPIFlash_Device_t *getFlashDevice(void); 80 | }; 81 | 82 | class Adafruit_FlashTransport_RP2040_CPY 83 | : public Adafruit_FlashTransport_RP2040 { 84 | 85 | public: 86 | Adafruit_FlashTransport_RP2040_CPY(bool idle = true) 87 | : Adafruit_FlashTransport_RP2040(CPY_START_ADDR, CPY_SIZE, idle) {} 88 | }; 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /.github/workflows/githubci.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: [pull_request, push, repository_dispatch] 4 | 5 | jobs: 6 | pre-commit: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Setup Python 10 | uses: actions/setup-python@v4 11 | with: 12 | python-version: '3.x' 13 | 14 | - name: Checkout code 15 | uses: actions/checkout@v3 16 | 17 | - name: Run pre-commit 18 | uses: pre-commit/action@v3.0.0 19 | 20 | - name: Checkout adafruit/ci-arduino 21 | uses: actions/checkout@v3 22 | with: 23 | repository: adafruit/ci-arduino 24 | path: ci 25 | 26 | - name: pre-install 27 | run: bash ci/actions_install.sh 28 | 29 | # clang is already run as part of pre-commit 30 | # - name: clang 31 | # run: python3 ci/run-clang-format.py -r src/arduino 32 | 33 | - name: doxygen 34 | env: 35 | GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }} 36 | PRETTYNAME : "Adafruit SPIFlash Library" 37 | run: bash ci/doxy_gen_and_deploy.sh 38 | 39 | build: 40 | strategy: 41 | fail-fast: false 42 | matrix: 43 | arduino-platform: 44 | - 'cpx_ada' 45 | - 'feather_m0_express' 46 | - 'metro_m0' 47 | - 'feather_m4_express' 48 | - 'metro_m4' 49 | - 'grand_central' 50 | - 'neotrellis_m4' 51 | - 'pyportal' 52 | - 'pyportal_titano' 53 | - 'matrixportal' 54 | - 'pybadge' 55 | - 'metroesp32s2' 56 | - 'nrf52840' 57 | - 'cpb' 58 | - 'clue' 59 | - 'feather_rp2040' 60 | - 'uno' 61 | 62 | runs-on: ubuntu-latest 63 | steps: 64 | - name: Setup Python 65 | uses: actions/setup-python@v4 66 | with: 67 | python-version: '3.x' 68 | 69 | - name: Checkout code 70 | uses: actions/checkout@v3 71 | 72 | - name: Checkout adafruit/ci-arduino 73 | uses: actions/checkout@v3 74 | with: 75 | repository: adafruit/ci-arduino 76 | path: ci 77 | 78 | - name: pre-install 79 | run: bash ci/actions_install.sh 80 | 81 | - name: test platforms 82 | run: python3 ci/build_platform.py ${{ matrix.arduino-platform }} 83 | 84 | - name: Move build artifacts into place 85 | run: | 86 | mkdir build 87 | find -name "*.uf2" -ls 88 | for i in examples/*/build/*/*.uf2; do if [ -f $i ]; then j=${i##*/}; j=${j%%*.}; mv $i build/$j-${{ matrix.arduino-platform }}.uf2; fi done 89 | 90 | - name: Upload build artifacts 91 | uses: actions/upload-artifact@v4 92 | with: 93 | name: ${{ github.event.repository.name }}.${{ github.sha }}.${{ matrix.arduino-platform }} 94 | path: | 95 | build/*.hex 96 | build/*.bin 97 | build/*.uf2 98 | 99 | - name: Zip release files 100 | if: startsWith(github.ref, 'refs/tags/') 101 | run: | 102 | if [ -d build ]; then 103 | ( 104 | echo "Built from Adafruit SPIFlash Library `git describe --tags` for ${{ matrix.arduino-platform }}" 105 | echo "Source code: https://github.com/adafruit/Adafruit_SPIFlash" 106 | echo "Adafruit Learning System: https://learn.adafruit.com/" 107 | ) > build/README.txt 108 | cd build && zip -9 -o ${{ matrix.arduino-platform }}.zip *.hex *.bin *.uf2 *.txt 109 | fi 110 | 111 | - name: Create release 112 | if: startsWith(github.ref, 'refs/tags/') 113 | uses: softprops/action-gh-release@v1 114 | with: 115 | files: build/${{ matrix.arduino-platform }}.zip 116 | fail_on_unmatched_files: false 117 | body: "Select the zip file corresponding to your board from the list below." 118 | -------------------------------------------------------------------------------- /examples/flash_speedtest/flash_speedtest.ino: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // Copyright (c) 2019 Ha Thach for Adafruit Industries 3 | 4 | #include "SdFat_Adafruit_Fork.h" 5 | #include 6 | 7 | #include "Adafruit_SPIFlash.h" 8 | 9 | // for flashTransport definition 10 | #include "flash_config.h" 11 | 12 | Adafruit_SPIFlash flash(&flashTransport); 13 | 14 | #ifdef __AVR__ 15 | #define BUFSIZE 512 16 | #else 17 | #define BUFSIZE 4096 18 | #endif 19 | 20 | #define TEST_WHOLE_CHIP 1 21 | 22 | #ifdef LED_BUILTIN 23 | uint8_t led_pin = LED_BUILTIN; 24 | #else 25 | uint8_t led_pin = 0; 26 | #endif 27 | 28 | // 4 byte aligned buffer has best result with nRF QSPI 29 | uint8_t bufwrite[BUFSIZE] __attribute__((aligned(4))); 30 | uint8_t bufread[BUFSIZE] __attribute__((aligned(4))); 31 | 32 | // the setup function runs once when you press reset or power the board 33 | void setup() { 34 | Serial.begin(115200); 35 | while (!Serial) { 36 | delay(100); // wait for native usb 37 | } 38 | flash.begin(); 39 | 40 | pinMode(led_pin, OUTPUT); 41 | flash.setIndicator(led_pin, true); 42 | 43 | Serial.println("Adafruit Serial Flash Speed Test example"); 44 | Serial.print("JEDEC ID: "); 45 | Serial.println(flash.getJEDECID(), HEX); 46 | Serial.print("Flash size: "); 47 | Serial.println(flash.size()); 48 | Serial.flush(); 49 | 50 | write_and_compare(0xAA); 51 | write_and_compare(0x55); 52 | 53 | Serial.println("Speed test is completed."); 54 | Serial.flush(); 55 | } 56 | 57 | void print_speed(const char *text, uint32_t count, uint32_t ms) { 58 | Serial.print(text); 59 | Serial.print(count); 60 | Serial.print(" bytes in "); 61 | Serial.print(ms / 1000.0F, 2); 62 | Serial.println(" seconds."); 63 | 64 | Serial.print("Speed: "); 65 | Serial.print((count / 1000.0F) / (ms / 1000.0F), 2); 66 | Serial.println(" KB/s.\r\n"); 67 | } 68 | 69 | bool write_and_compare(uint8_t pattern) { 70 | uint32_t ms; 71 | 72 | Serial.println("Erase chip"); 73 | Serial.flush(); 74 | 75 | #if TEST_WHOLE_CHIP 76 | uint32_t const flash_sz = flash.size(); 77 | flash.eraseChip(); 78 | #else 79 | uint32_t const flash_sz = 4096; 80 | flash.eraseSector(0); 81 | #endif 82 | 83 | flash.waitUntilReady(); 84 | 85 | // write all 86 | memset(bufwrite, (int)pattern, sizeof(bufwrite)); 87 | Serial.print("Write flash with 0x"); 88 | Serial.println(pattern, HEX); 89 | Serial.flush(); 90 | ms = millis(); 91 | 92 | for (uint32_t addr = 0; addr < flash_sz; addr += sizeof(bufwrite)) { 93 | flash.writeBuffer(addr, bufwrite, sizeof(bufwrite)); 94 | } 95 | 96 | uint32_t ms_write = millis() - ms; 97 | print_speed("Write ", flash_sz, ms_write); 98 | Serial.flush(); 99 | 100 | // read and compare 101 | Serial.println("Read flash and compare"); 102 | Serial.flush(); 103 | uint32_t ms_read = 0; 104 | for (uint32_t addr = 0; addr < flash_sz; addr += sizeof(bufread)) { 105 | memset(bufread, 0, sizeof(bufread)); 106 | 107 | ms = millis(); 108 | flash.readBuffer(addr, bufread, sizeof(bufread)); 109 | ms_read += millis() - ms; 110 | 111 | if (memcmp(bufwrite, bufread, BUFSIZE)) { 112 | Serial.print("Error: flash contents mismatched at address 0x"); 113 | Serial.println(addr, HEX); 114 | for (uint32_t i = 0; i < sizeof(bufread); i++) { 115 | if (i != 0) 116 | Serial.print(' '); 117 | if ((i % 16 == 0)) { 118 | Serial.println(); 119 | if (i < 0x100) 120 | Serial.print('0'); 121 | if (i < 0x010) 122 | Serial.print('0'); 123 | Serial.print(i, HEX); 124 | Serial.print(": "); 125 | } 126 | 127 | if (bufread[i] < 0x10) 128 | Serial.print('0'); 129 | Serial.print(bufread[i], HEX); 130 | } 131 | 132 | Serial.println(); 133 | return false; 134 | } 135 | } 136 | 137 | print_speed("Read ", flash_sz, ms_read); 138 | Serial.flush(); 139 | 140 | return true; 141 | } 142 | 143 | void loop() { 144 | // nothing to do 145 | } 146 | -------------------------------------------------------------------------------- /examples/SdFat_circuitpython/SdFat_circuitpython.ino: -------------------------------------------------------------------------------- 1 | // Adafruit M0 Express CircuitPython Flash Example 2 | // Author: Tony DiCola 3 | // 4 | // This is an example of reading and writing data from Arduino 5 | // to the M0 Express flash filesystem used by CircuitPython. 6 | // You can create, update, and read files on the CircuitPython 7 | // filesystem in an Arduino sketch and then later load CircuitPython 8 | // to interact with the same files. This example will print out 9 | // the contents of boot.py and main.py (if found) and add a line 10 | // to a data.txt file on CircuitPython's filesystem. 11 | // 12 | // Note before you use this sketch you must load CircuitPython 13 | // on your M0 Express. This will create the filesystem and 14 | // initialize it, then you can load this example and read/write 15 | // files on the board. 16 | // 17 | // Usage: 18 | // - Modify the pins and type of fatfs object in the config 19 | // section below if necessary (usually not necessary). 20 | // - Upload this sketch to your M0 express board. 21 | // - Open the serial monitor at 115200 baud. You should see the 22 | // example start to run and messages printed to the monitor. 23 | // If you don't see anything close the serial monitor, press 24 | // the board reset button, wait a few seconds, then open the 25 | // serial monitor again. 26 | #include 27 | 28 | #include "SdFat_Adafruit_Fork.h" 29 | 30 | #include 31 | 32 | // for flashTransport definition 33 | #include "flash_config.h" 34 | 35 | Adafruit_SPIFlash flash(&flashTransport); 36 | 37 | // file system object from SdFat 38 | FatVolume fatfs; 39 | 40 | void setup() { 41 | // Initialize serial port and wait for it to open before continuing. 42 | Serial.begin(115200); 43 | while (!Serial) { 44 | delay(100); 45 | } 46 | Serial.println("Adafruit SPIFlash CircuitPython Example"); 47 | 48 | // Initialize flash library and check its chip ID. 49 | if (!flash.begin()) { 50 | Serial.println("Error, failed to initialize flash chip!"); 51 | while (1) { 52 | } 53 | } 54 | Serial.print("Flash chip JEDEC ID: 0x"); 55 | Serial.println(flash.getJEDECID(), HEX); 56 | 57 | // First call begin to mount the filesystem. Check that it returns true 58 | // to make sure the filesystem was mounted. 59 | if (!fatfs.begin(&flash)) { 60 | Serial.println("Failed to mount filesystem!"); 61 | Serial.println("Was CircuitPython loaded on the board first to create the " 62 | "filesystem?"); 63 | while (1) { 64 | } 65 | } 66 | Serial.println("Mounted filesystem!"); 67 | 68 | // Check if a boot.py exists and print it out. 69 | if (fatfs.exists("boot.py")) { 70 | File32 bootPy = fatfs.open("boot.py", FILE_READ); 71 | Serial.println("Printing boot.py..."); 72 | while (bootPy.available()) { 73 | char c = bootPy.read(); 74 | Serial.print(c); 75 | } 76 | Serial.println(); 77 | } else { 78 | Serial.println("No boot.py found..."); 79 | } 80 | 81 | // Check if a main.py exists and print it out: 82 | if (fatfs.exists("code.py")) { 83 | File32 mainPy = fatfs.open("code.py", FILE_READ); 84 | Serial.println("Printing code.py..."); 85 | while (mainPy.available()) { 86 | char c = mainPy.read(); 87 | Serial.print(c); 88 | } 89 | Serial.println(); 90 | } else { 91 | Serial.println("No code.py found..."); 92 | } 93 | 94 | // Create or append to a data.txt file and add a new line 95 | // to the end of it. CircuitPython code can later open and 96 | // see this file too! 97 | File32 data = fatfs.open("data.txt", FILE_WRITE); 98 | if (data) { 99 | // Write a new line to the file: 100 | data.println("Hello CircuitPython from Arduino!"); 101 | data.close(); 102 | // See the other fatfs examples like fatfs_full_usage and fatfs_datalogging 103 | // for more examples of interacting with files. 104 | Serial.println("Wrote a new line to the end of data.txt!"); 105 | } else { 106 | Serial.println("Error, failed to open data file for writing!"); 107 | } 108 | 109 | Serial.println("Finished!"); 110 | } 111 | 112 | void loop() { 113 | // Nothing to do in the loop. 114 | delay(100); 115 | } 116 | -------------------------------------------------------------------------------- /examples/flash_info/flash_info.ino: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // Copyright (c) 2019 Ha Thach for Adafruit Industries 3 | 4 | #include "SdFat_Adafruit_Fork.h" 5 | #include 6 | 7 | #include 8 | 9 | // for flashTransport definition 10 | #include "flash_config.h" 11 | 12 | Adafruit_SPIFlash flash(&flashTransport); 13 | 14 | /* If you want to use a specific flash device, for example for a custom built 15 | board, first look for it in Adafruit_SPIFlash\src\flash_devices.h 16 | * If it isn't in there you need to create your own definition like the 17 | W25Q80DLX_EXAMPLE example below. 18 | * These definitions need to be edited to match information on the data sheet 19 | of the flash device that you want to use. 20 | * If you are not sure what the manufacture ID, memory type and capacity values 21 | should be, try running the sketch anyway and look at the serial output 22 | * The flash device will report these values to you as a single hexadecimal 23 | value (the JDEC ID) 24 | * For example, the first device on the list - the W25Q80DLX - will report its 25 | JDEC ID as 0xef4014, which is made of these three values: 26 | * manufacturer_id = 0xef 27 | * memory_type = 0x40 28 | * capacity = 0x14 29 | * With this macro properly defined you can then create an array of device 30 | definitions as shown below, this can include any from the list of devices in 31 | flash_devices.h, and any you define yourself here 32 | * You need to update the variable on line 71 to reflect the number of items in 33 | the array 34 | * You also need to uncomment line 84 and comment out line 81 so this array 35 | will be passed to the flash memory driver. 36 | * 37 | * Example of a user defined flash memory device: 38 | #define W25Q80DLX_EXAMPLE \ 39 | { \ 40 | .total_size = 1*1024*1024, \ 41 | .start_up_time_us = 5000, .manufacturer_id = 0xef, \ 42 | .memory_type = 0x40, .capacity = 0x14, .max_clock_speed_mhz = 80, \ 43 | .quad_enable_bit_mask = 0x02, .has_sector_protection = false, \ 44 | .supports_fast_read = true, .supports_qspi = true, \ 45 | .supports_qspi_writes = false, .write_status_register_split = false, \ 46 | .single_status_byte = false, .is_fram = false, \ 47 | } 48 | */ 49 | 50 | /* 51 | * Create an array of data structures and fill it with the settings we defined 52 | * above. We are using two devices, but more can be added if you want. 53 | */ 54 | // static const SPIFlash_Device_t my_flash_devices[] = { 55 | // W25Q80DLX_EXAMPLE, 56 | // }; 57 | /* 58 | * Specify the number of different devices that are listed in the array we just 59 | * created. If you add more devices to the array, update this value to match. 60 | */ 61 | // const int flashDevices = 1; 62 | 63 | // the setup function runs once when you press reset or power the board 64 | void setup() { 65 | Serial.begin(115200); 66 | while (!Serial) { 67 | delay(100); // wait for native usb 68 | } 69 | 70 | Serial.println("Adafruit Serial Flash Info example"); 71 | flash.begin(); 72 | 73 | // Using a flash device not already listed? Start the flash memory by passing 74 | // it the array of device settings defined above, and the number of elements 75 | // in the array. 76 | // flash.begin(my_flash_devices, flashDevices); 77 | 78 | uint32_t jedec_id = flash.getJEDECID(); 79 | Serial.print("JEDEC ID: 0x"); 80 | Serial.println(jedec_id, HEX); 81 | Serial.print("Flash size (usable): "); 82 | Serial.print(flash.size() / 1024); 83 | Serial.println(" KB"); 84 | 85 | #ifdef ARDUINO_ARCH_RP2040 86 | // For rp2 since flash device is also used for storing code, the flash.size() 87 | // only return usable flash size for data which is dictated by e.g Menu->Flash 88 | // Size -> 2MB (Sketch 1920KB, FS 64KB) --> size = 64KB For reference purpose, 89 | // we only try to find and print actual flash device size using JEDEC here 90 | Serial.print("Flash size (raw): "); 91 | Serial.print(1 << ((jedec_id & 0xff) - 10)); 92 | Serial.println(" KB"); 93 | #endif 94 | } 95 | 96 | void loop() { 97 | // nothing to do 98 | } 99 | -------------------------------------------------------------------------------- /src/Adafruit_SPIFlash.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 Ha Thach and Dean Miller for Adafruit Industries LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef ADAFRUIT_SPIFLASH_H_ 26 | #define ADAFRUIT_SPIFLASH_H_ 27 | 28 | #include "Adafruit_FlashCache.h" 29 | #include "Adafruit_SPIFlashBase.h" 30 | 31 | // implement SdFat Block Driver 32 | #include "SdFat_Adafruit_Fork.h" 33 | 34 | #if SD_FAT_VERSION >= 20000 35 | 36 | #if USE_BLOCK_DEVICE_INTERFACE == 0 37 | #error USE_BLOCK_DEVICE_INTERFACE must be defined to 1 in SdFatConfig.h. Make sure you use the Adafruit Fork at 'https://github.com/adafruit/SdFat' 38 | #endif 39 | 40 | #else 41 | 42 | #if ENABLE_EXTENDED_TRANSFER_CLASS == 0 43 | #error ENABLE_EXTENDED_TRANSFER_CLASS must be set to 1 in SdFatConfig.h. Make sure you use the Adafruit Fork at 'https://github.com/adafruit/SdFat' 44 | #endif 45 | 46 | // Try our best to be forward-compatible with v2 47 | #define FsBlockDeviceInterface BaseBlockDriver 48 | #define FatVolume FatFileSystem 49 | #define File32 File 50 | 51 | #endif // SD_FAT_VERSION 52 | 53 | #if FAT12_SUPPORT == 0 54 | #error FAT12_SUPPORT must be set to 1 in SdFat SdFatConfig.h. Make sure you use the Adafruit Fork at 'https://github.com/adafruit/SdFat' 55 | #endif 56 | 57 | // This class extends Adafruit_SPIFlashBase by adding support for the 58 | // BaseBlockDriver interface. This allows it to be used with SdFat's 59 | // FatFileSystem class. 60 | // 61 | // Instances of this class will use 4kB of RAM as a block cache. 62 | class Adafruit_SPIFlash : public FsBlockDeviceInterface, 63 | public Adafruit_SPIFlashBase { 64 | public: 65 | Adafruit_SPIFlash(); 66 | Adafruit_SPIFlash(Adafruit_FlashTransport *transport, bool useCache = true); 67 | ~Adafruit_SPIFlash() {} 68 | 69 | bool begin(SPIFlash_Device_t const *flash_devs = NULL, size_t count = 1); 70 | void end(void); 71 | 72 | bool isCached(void) { return _cache_en && (_cache != NULL); } 73 | 74 | //------------- SdFat v2 FsBlockDeviceInterface API -------------// 75 | virtual bool isBusy(); 76 | virtual uint32_t sectorCount(); 77 | virtual bool syncDevice(); 78 | 79 | virtual bool readSector(uint32_t block, uint8_t *dst); 80 | virtual bool readSectors(uint32_t block, uint8_t *dst, size_t ns); 81 | virtual bool writeSector(uint32_t block, const uint8_t *src); 82 | virtual bool writeSectors(uint32_t block, const uint8_t *src, size_t ns); 83 | 84 | // SdFat v1 BaseBlockDRiver API for backward-compatible 85 | virtual bool syncBlocks() { return syncDevice(); } 86 | 87 | virtual bool readBlock(uint32_t block, uint8_t *dst) { 88 | return readSector(block, dst); 89 | } 90 | 91 | virtual bool readBlocks(uint32_t block, uint8_t *dst, size_t nb) { 92 | return readSectors(block, dst, nb); 93 | } 94 | 95 | virtual bool writeBlock(uint32_t block, const uint8_t *src) { 96 | return writeSector(block, src); 97 | } 98 | 99 | virtual bool writeBlocks(uint32_t block, const uint8_t *src, size_t nb) { 100 | return writeSectors(block, src, nb); 101 | } 102 | 103 | protected: 104 | bool _cache_en; 105 | Adafruit_FlashCache *_cache; 106 | }; 107 | 108 | #endif /* ADAFRUIT_SPIFLASH_H_ */ 109 | -------------------------------------------------------------------------------- /tools/build_all.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import subprocess 4 | from subprocess import Popen, PIPE 5 | import time 6 | import glob 7 | from multiprocessing import Pool 8 | 9 | SUCCEEDED = "\033[32msucceeded\033[0m" 10 | FAILED = "\033[31mfailed\033[0m" 11 | SKIPPED = "\033[35mskipped\033[0m" 12 | WARNING = "\033[33mwarnings\033[0m " 13 | 14 | build_format = '| {:35} | {:9} | {:6} |' 15 | build_separator = '-' * 59 16 | 17 | # ci-arduino naming, fqbn 18 | all_boards = [ 19 | ["uno", "arduino:avr:uno"], 20 | ['metro_m0_tinyusb', 'adafruit:samd:adafruit_metro_m0:usbstack=tinyusb'], 21 | ['metro_m4_tinyusb', 'adafruit:samd:adafruit_metro_m4:speed=120,usbstack=tinyusb'], 22 | ['nrf52840', 'adafruit:nrf52:feather52840'], 23 | ['feather_rp2040_tinyusb', 'rp2040:rp2040:adafruit_feather:flash=8388608_0,freq=125,dbgport=Disabled,dbglvl=None,usbstack=tinyusb'], 24 | ['metroesp32s2', 'espressif:esp32:adafruit_metro_esp32s2:CDCOnBoot=cdc,MSCOnBoot=default,DFUOnBoot=default,UploadMode=cdc,PSRAM=enabled,PartitionScheme=tinyuf2'], 25 | ['feather_esp32s3', 'espressif:esp32:adafruit_feather_esp32s3:FlashMode=qio,LoopCore=1,EventsCore=1,USBMode=default,CDCOnBoot=cdc,MSCOnBoot=default,DFUOnBoot=default,UploadMode=cdc,PartitionScheme=tinyuf2'], 26 | ] 27 | 28 | # return [succeeded, failed, skipped] 29 | def build_sketch(variant, sketch): 30 | ret = [0, 0, 0] 31 | 32 | name = variant[0] 33 | fqbn = variant[1] 34 | 35 | start_time = time.monotonic() 36 | # Skip if contains: ".board.test.skip" or ".all.test.skip" 37 | # Skip if not contains: ".board.test.only" for a specific board 38 | sketchdir = os.path.dirname(sketch) 39 | if os.path.exists(sketchdir + '/.all.test.skip') or os.path.exists(sketchdir + '/.' + name + '.test.skip') or \ 40 | (glob.glob(sketchdir + "/.*.test.only") and not os.path.exists(sketchdir + '/.' + name + '.test.only')): 41 | success = SKIPPED 42 | ret[2] = 1 43 | else: 44 | build_result = subprocess.run("arduino-cli compile --warnings all --fqbn {} {}".format(fqbn, sketch), 45 | shell=True, stdout=PIPE, stderr=PIPE) 46 | 47 | # get stderr into a form where warning/error was output to stderr 48 | if build_result.returncode != 0: 49 | success = FAILED 50 | ret[1] = 1 51 | else: 52 | ret[0] = 1 53 | if build_result.stderr: 54 | success = WARNING 55 | else: 56 | success = SUCCEEDED 57 | 58 | build_duration = time.monotonic() - start_time 59 | print(build_format.format(os.path.basename(sketch), success, '{:5.2f}s'.format(build_duration))) 60 | 61 | if success != SKIPPED: 62 | # Build failed 63 | if build_result.returncode != 0: 64 | print(build_result.stdout.decode("utf-8")) 65 | 66 | # Build with warnings 67 | if build_result.stderr: 68 | print(build_result.stderr.decode("utf-8")) 69 | return ret 70 | 71 | 72 | # return [succeeded, failed, skipped] 73 | def build_variant(variant): 74 | print() 75 | print(build_separator) 76 | print('| {:^56} |'.format('Board ' + variant[0])) 77 | print(build_separator) 78 | print(build_format.format('Example', '\033[39mResult\033[0m', 'Time')) 79 | print(build_separator) 80 | 81 | with Pool(processes=os.cpu_count()) as pool: 82 | pool_args = list((map(lambda e, v=variant: [v, e], all_examples))) 83 | result = pool.starmap(build_sketch, pool_args) 84 | # sum all element of same index (column sum) 85 | return list(map(sum, list(zip(*result)))) 86 | 87 | 88 | if __name__ == '__main__': 89 | # build all variants if input not existed 90 | if len(sys.argv) > 1: 91 | build_boards = list(filter(lambda x: sys.argv[1] in x[0], all_boards)) 92 | else: 93 | build_boards = all_boards 94 | 95 | all_examples = list(glob.iglob('examples/**/*.ino', recursive=True)) 96 | all_examples.sort() 97 | 98 | total_time = time.monotonic() 99 | total_result = [0, 0, 0] 100 | for b in build_boards: 101 | ret = build_variant(b) 102 | total_result = list(map(lambda x, y: x + y, total_result, ret)) 103 | 104 | # Build Summary 105 | total_time = time.monotonic() - total_time 106 | print(build_separator) 107 | print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(total_result[0], SUCCEEDED, total_result[1], 108 | FAILED, total_result[2], SKIPPED, total_time)) 109 | print(build_separator) 110 | sys.exit(total_result[1]) 111 | -------------------------------------------------------------------------------- /src/Adafruit_FlashCache.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 hathach for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #include "Adafruit_FlashCache.h" 26 | #include "Adafruit_SPIFlashBase.h" 27 | 28 | #if SPIFLASH_DEBUG 29 | #define SPICACHE_LOG(_new_addr) \ 30 | do { \ 31 | Serial.print(__FUNCTION__); \ 32 | Serial.print(": flush sector = "); \ 33 | Serial.print(_addr / 512); \ 34 | Serial.print(", new sector = "); \ 35 | Serial.println(_new_addr / 512); \ 36 | } while (0) 37 | #else 38 | #define SPICACHE_LOG(_new_addr) 39 | #endif 40 | 41 | #define INVALID_ADDR 0xffffffff 42 | 43 | static inline uint32_t sector_of(uint32_t addr) { 44 | return addr & ~(SFLASH_SECTOR_SIZE - 1); 45 | } 46 | 47 | static inline uint32_t offset_of(uint32_t addr) { 48 | return addr & (SFLASH_SECTOR_SIZE - 1); 49 | } 50 | 51 | Adafruit_FlashCache::Adafruit_FlashCache(void) { _addr = INVALID_ADDR; } 52 | 53 | bool Adafruit_FlashCache::sync(Adafruit_SPIFlashBase *fl) { 54 | if (_addr == INVALID_ADDR) { 55 | return true; 56 | } 57 | 58 | fl->eraseSector(_addr / SFLASH_SECTOR_SIZE); 59 | fl->writeBuffer(_addr, _buf, SFLASH_SECTOR_SIZE); 60 | 61 | _addr = INVALID_ADDR; 62 | 63 | return true; 64 | } 65 | 66 | bool Adafruit_FlashCache::write(Adafruit_SPIFlashBase *fl, uint32_t address, 67 | void const *src, uint32_t len) { 68 | uint8_t const *src8 = (uint8_t const *)src; 69 | uint32_t remain = len; 70 | 71 | // Program up to sector boundary each loop 72 | while (remain) { 73 | uint32_t const sector_addr = sector_of(address); 74 | uint32_t const offset = offset_of(address); 75 | 76 | uint32_t wr_bytes = SFLASH_SECTOR_SIZE - offset; 77 | wr_bytes = min(remain, wr_bytes); 78 | 79 | // Flash sector changes, flush old and update new cache 80 | if (sector_addr != _addr) { 81 | SPICACHE_LOG(sector_addr); 82 | this->sync(fl); 83 | _addr = sector_addr; 84 | 85 | // read a whole page from flash 86 | fl->readBuffer(sector_addr, _buf, SFLASH_SECTOR_SIZE); 87 | } 88 | 89 | memcpy(_buf + offset, src8, wr_bytes); 90 | 91 | // adjust for next run 92 | src8 += wr_bytes; 93 | remain -= wr_bytes; 94 | address += wr_bytes; 95 | } 96 | 97 | return true; 98 | } 99 | 100 | bool Adafruit_FlashCache::read(Adafruit_SPIFlashBase *fl, uint32_t address, 101 | uint8_t *buffer, uint32_t count) { 102 | // overwrite with cache value if available 103 | if ((_addr != INVALID_ADDR) && 104 | !(address < _addr && address + count <= _addr) && 105 | !(address >= _addr + SFLASH_SECTOR_SIZE)) { 106 | int32_t dst_off = _addr - address; 107 | int32_t src_off = 0; 108 | 109 | if (dst_off < 0) { 110 | src_off = -dst_off; 111 | dst_off = 0; 112 | } 113 | 114 | int32_t cache_bytes = min((int32_t)(SFLASH_SECTOR_SIZE - src_off), 115 | (int32_t)(count - dst_off)); 116 | 117 | // start to cached 118 | if (dst_off) { 119 | fl->readBuffer(address, buffer, dst_off); 120 | } 121 | 122 | // cached 123 | memcpy(buffer + dst_off, _buf + src_off, cache_bytes); 124 | 125 | // cached to end 126 | uint32_t copied = (uint32_t)(dst_off + cache_bytes); 127 | if (copied < count) { 128 | fl->readBuffer(address + copied, buffer + copied, count - copied); 129 | } 130 | } else { 131 | fl->readBuffer(address, buffer, count); 132 | } 133 | 134 | return true; 135 | } 136 | -------------------------------------------------------------------------------- /src/esp32/Adafruit_FlashTransport_ESP32.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2020 hathach for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #include "Adafruit_FlashTransport.h" 26 | 27 | #ifdef ARDUINO_ARCH_ESP32 28 | 29 | #include "esp_flash.h" 30 | 31 | Adafruit_FlashTransport_ESP32::Adafruit_FlashTransport_ESP32(void) { 32 | _cmd_read = SFLASH_CMD_READ; 33 | _addr_len = 3; // work with most device if not set 34 | 35 | _partition = NULL; 36 | memset(&_flash_device, 0, sizeof(_flash_device)); 37 | } 38 | 39 | void Adafruit_FlashTransport_ESP32::begin(void) { 40 | _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, 41 | ESP_PARTITION_SUBTYPE_DATA_FAT, NULL); 42 | 43 | if (!_partition) { 44 | log_printf("SPIFlash: No FAT partition found"); 45 | } 46 | } 47 | 48 | void Adafruit_FlashTransport_ESP32::end(void) { 49 | _cmd_read = SFLASH_CMD_READ; 50 | _addr_len = 3; // work with most device if not set 51 | 52 | _partition = NULL; 53 | memset(&_flash_device, 0, sizeof(_flash_device)); 54 | } 55 | 56 | SPIFlash_Device_t *Adafruit_FlashTransport_ESP32::getFlashDevice(void) { 57 | if (!_partition) { 58 | return NULL; 59 | } 60 | 61 | // Limit to partition size 62 | _flash_device.total_size = _partition->size; 63 | 64 | esp_flash_t const *flash = _partition->flash_chip; 65 | _flash_device.manufacturer_id = (flash->chip_id >> 16); 66 | _flash_device.memory_type = (flash->chip_id >> 8) & 0xff; 67 | _flash_device.capacity = flash->chip_id & 0xff; 68 | 69 | return &_flash_device; 70 | } 71 | 72 | void Adafruit_FlashTransport_ESP32::setClockSpeed(uint32_t write_hz, 73 | uint32_t read_hz) { 74 | // do nothing, just use current configured clock 75 | (void)write_hz; 76 | (void)read_hz; 77 | } 78 | 79 | bool Adafruit_FlashTransport_ESP32::runCommand(uint8_t command) { 80 | switch (command) { 81 | case SFLASH_CMD_ERASE_CHIP: 82 | return ESP_OK == esp_partition_erase_range(_partition, 0, _partition->size); 83 | 84 | // do nothing, mostly write enable 85 | default: 86 | return true; 87 | } 88 | } 89 | 90 | bool Adafruit_FlashTransport_ESP32::readCommand(uint8_t command, 91 | uint8_t *response, 92 | uint32_t len) { 93 | // mostly is Read STATUS, just fill with 0x0 94 | (void)command; 95 | memset(response, 0, len); 96 | 97 | return true; 98 | } 99 | 100 | bool Adafruit_FlashTransport_ESP32::writeCommand(uint8_t command, 101 | uint8_t const *data, 102 | uint32_t len) { 103 | // mostly is Write Status, do nothing 104 | (void)command; 105 | (void)data; 106 | (void)len; 107 | 108 | return true; 109 | } 110 | 111 | bool Adafruit_FlashTransport_ESP32::eraseCommand(uint8_t command, 112 | uint32_t addr) { 113 | uint32_t erase_sz; 114 | 115 | if (command == SFLASH_CMD_ERASE_SECTOR) { 116 | erase_sz = SFLASH_SECTOR_SIZE; 117 | } else if (command == SFLASH_CMD_ERASE_BLOCK) { 118 | erase_sz = SFLASH_BLOCK_SIZE; 119 | } else { 120 | return false; 121 | } 122 | 123 | return ESP_OK == esp_partition_erase_range(_partition, addr, erase_sz); 124 | } 125 | 126 | bool Adafruit_FlashTransport_ESP32::readMemory(uint32_t addr, uint8_t *data, 127 | uint32_t len) { 128 | return ESP_OK == esp_partition_read(_partition, addr, data, len); 129 | } 130 | 131 | bool Adafruit_FlashTransport_ESP32::writeMemory(uint32_t addr, 132 | uint8_t const *data, 133 | uint32_t len) { 134 | return ESP_OK == esp_partition_write(_partition, addr, data, len); 135 | } 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /examples/SdFat_circuitpython_backupFiles/SdFat_circuitpython_backupFiles.ino: -------------------------------------------------------------------------------- 1 | // Adafruit M0 Express CircuitPython Repair 2 | // Author: Limor Fried 3 | // 4 | /* 5 | * This script can be useful if you seriously bork up your CircuitPython 6 | * install. It will find any files named main.py, boot.py, main.txt, code.py 7 | * or code.txt and move them to backup files. its a tad slow but then you 8 | * can reload circuitpython safely. This example right now is only for 9 | * the Metro M0 Express & Circuit Playground M0 but i have a... 10 | * 11 | * TODO: automagically detect if it's Feather/Metro/CircuitPlayground! 12 | */ 13 | 14 | #include "SdFat_Adafruit_Fork.h" 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | // for flashTransport definition 21 | #include "flash_config.h" 22 | 23 | Adafruit_SPIFlash flash(&flashTransport); 24 | 25 | // file system object from SdFat 26 | FatVolume fatfs; 27 | 28 | #define NEOPIN 40 // neopixel pin 29 | #define BUFFERSIZ 200 30 | 31 | Adafruit_NeoPixel pixel = Adafruit_NeoPixel(1, NEOPIN, NEO_GRB + NEO_KHZ800); 32 | 33 | void setup() { 34 | Serial.begin(115200); 35 | // while (!Serial); 36 | delay(1000); // small delay in case we want to watch it on the serial port 37 | Serial.println("Adafruit Express CircuitPython Flash Repair"); 38 | 39 | pixel.begin(); // This initializes the NeoPixel library 40 | pixel.setBrightness(30); // not too bright! 41 | 42 | // Initialize flash library and check its chip ID. 43 | if (!flash.begin()) { 44 | Serial.println("Error, failed to initialize flash chip!"); 45 | error(1); 46 | } 47 | Serial.print("Flash chip JEDEC ID: 0x"); 48 | Serial.println(flash.getJEDECID(), HEX); 49 | 50 | // First call begin to mount the filesystem. Check that it returns true 51 | // to make sure the filesystem was mounted. 52 | if (!fatfs.begin(&flash)) { 53 | Serial.println("Failed to mount filesystem!"); 54 | Serial.println("Was CircuitPython loaded on the board first to create the " 55 | "filesystem?"); 56 | error(3); 57 | } 58 | Serial.println("Mounted filesystem!"); 59 | 60 | moveFile("boot.py", "bootpy.bak"); 61 | moveFile("main.py", "mainpy.bak"); 62 | moveFile("main.txt", "maintxt.bak"); 63 | moveFile("code.py", "codepy.bak"); 64 | moveFile("code.txt", "codetxt.bak"); 65 | 66 | Serial.println("Finished!"); 67 | } 68 | 69 | uint8_t i = 0; 70 | void loop() { 71 | // white pixel pulse -> we're done 72 | pixel.setPixelColor(0, pixel.Color(i, i, i)); 73 | pixel.show(); 74 | i++; 75 | delay(5); 76 | } 77 | 78 | boolean moveFile(const char *file, const char *dest) { 79 | if (!fatfs.exists(file)) { 80 | Serial.print(file); 81 | Serial.println(" not found"); 82 | return false; 83 | } 84 | if (fatfs.exists(dest)) { 85 | Serial.println("Found old backup, removing..."); 86 | if (!fatfs.remove(dest)) { 87 | Serial.println("Error, couldn't delete "); 88 | Serial.print(dest); 89 | Serial.println(" file!"); 90 | error(4); 91 | } 92 | } 93 | 94 | pixel.setPixelColor(0, pixel.Color(100, 100, 0)); 95 | pixel.show(); 96 | 97 | File32 source = fatfs.open(file, FILE_READ); 98 | File32 backup = fatfs.open(dest, FILE_WRITE); 99 | Serial.println("Making backup!"); 100 | Serial.println("\n---------------------\n"); 101 | 102 | while (1) { 103 | int avail = source.available(); 104 | // Serial.print("**Available bytes: "); Serial.print(avail); 105 | // Serial.print("**"); 106 | if (avail == 0) { 107 | Serial.println("\n---------------------\n"); 108 | break; 109 | } 110 | int toread = min(BUFFERSIZ - 1, avail); 111 | char buffer[BUFFERSIZ]; 112 | 113 | int numread = source.read(buffer, toread); 114 | if (numread != toread) { 115 | Serial.print("Failed to read "); 116 | Serial.print(toread); 117 | Serial.print(" bytes, got "); 118 | Serial.print(numread); 119 | error(5); 120 | } 121 | buffer[toread] = 0; 122 | Serial.print(buffer); 123 | if ((int)backup.write(buffer, toread) != toread) { 124 | Serial.println("Error, couldn't write data to backup file!"); 125 | error(6); 126 | } 127 | } 128 | 129 | pixel.setPixelColor(0, pixel.Color(100, 0, 100)); 130 | pixel.show(); 131 | 132 | Serial.print("Original file size: "); 133 | Serial.println(source.size()); 134 | Serial.print("Backup file size: "); 135 | Serial.println(backup.size()); 136 | backup.close(); 137 | if (source.size() == backup.size()) { 138 | if (!fatfs.remove(file)) { 139 | Serial.print("Error, couldn't delete "); 140 | Serial.println(file); 141 | error(10); 142 | } 143 | } 144 | pixel.setPixelColor(0, pixel.Color(0, 100, 0)); 145 | pixel.show(); 146 | delay(100); 147 | return true; 148 | } 149 | 150 | void error(uint8_t i) { 151 | while (1) { 152 | for (int x = 0; x < i; x++) { 153 | pixel.setPixelColor(0, pixel.Color(100, 0, 0)); 154 | pixel.show(); 155 | delay(200); 156 | pixel.setPixelColor(0, pixel.Color(0, 0, 0)); 157 | pixel.show(); 158 | delay(200); 159 | } 160 | delay(1000); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/Adafruit_FlashTransport.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 hathach for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef ADAFRUIT_FLASHTRANSPORT_H_ 26 | #define ADAFRUIT_FLASHTRANSPORT_H_ 27 | 28 | #include 29 | #include 30 | 31 | enum { 32 | SFLASH_CMD_READ = 0x03, // Single Read 33 | SFLASH_CMD_FAST_READ = 0x0B, // Fast Read 34 | SFLASH_CMD_QUAD_READ = 0x6B, // 1 line address, 4 line data 35 | 36 | SFLASH_CMD_READ_JEDEC_ID = 0x9f, 37 | 38 | SFLASH_CMD_PAGE_PROGRAM = 0x02, 39 | SFLASH_CMD_QUAD_PAGE_PROGRAM = 0x32, // 1 line address, 4 line data 40 | 41 | SFLASH_CMD_READ_STATUS = 0x05, 42 | SFLASH_CMD_READ_STATUS2 = 0x35, 43 | 44 | SFLASH_CMD_WRITE_STATUS = 0x01, 45 | SFLASH_CMD_WRITE_STATUS2 = 0x31, 46 | 47 | SFLASH_CMD_ENABLE_RESET = 0x66, 48 | SFLASH_CMD_RESET = 0x99, 49 | 50 | SFLASH_CMD_WRITE_ENABLE = 0x06, 51 | SFLASH_CMD_WRITE_DISABLE = 0x04, 52 | 53 | SFLASH_CMD_ERASE_PAGE = 0x81, 54 | SFLASH_CMD_ERASE_SECTOR = 0x20, 55 | SFLASH_CMD_ERASE_BLOCK = 0xD8, 56 | SFLASH_CMD_ERASE_CHIP = 0xC7, 57 | 58 | SFLASH_CMD_4_BYTE_ADDR = 0xB7, 59 | SFLASH_CMD_3_BYTE_ADDR = 0xE9, 60 | }; 61 | 62 | /// Constant that is (mostly) true to all external flash devices 63 | enum { 64 | SFLASH_BLOCK_SIZE = 64 * 1024UL, 65 | SFLASH_SECTOR_SIZE = 4 * 1024, 66 | SFLASH_PAGE_SIZE = 256, 67 | }; 68 | 69 | class Adafruit_FlashTransport { 70 | public: 71 | virtual void begin(void) = 0; 72 | virtual void end(void) = 0; 73 | 74 | virtual bool supportQuadMode(void) = 0; 75 | 76 | /// Set clock speed in hertz 77 | /// @param write_hz Write clock speed in hertz 78 | /// @param read_hz Read clock speed in hertz 79 | virtual void setClockSpeed(uint32_t write_hz, uint32_t read_hz) = 0; 80 | 81 | /// Execute a single byte command e.g Reset, Write Enable 82 | /// @param command command code 83 | /// @return true if success 84 | virtual bool runCommand(uint8_t command) = 0; 85 | 86 | /// Execute a command with response data e.g Read Status, Read JEDEC 87 | /// @param command command code 88 | /// @param response buffer to hold data 89 | /// @param len number of bytes to read 90 | /// @return true if success 91 | virtual bool readCommand(uint8_t command, uint8_t *response, 92 | uint32_t len) = 0; 93 | 94 | /// Execute a command with data e.g Write Status, 95 | /// @param command command code 96 | /// @param data writing data 97 | /// @param len number of bytes to read 98 | /// @return true if success 99 | virtual bool writeCommand(uint8_t command, uint8_t const *data, 100 | uint32_t len) = 0; 101 | 102 | /// Erase external flash by address 103 | /// @param command can be sector erase (0x20) or block erase 0xD8 104 | /// @param address address to be erased 105 | /// @return true if success 106 | virtual bool eraseCommand(uint8_t command, uint32_t address) = 0; 107 | 108 | /// Read data from external flash contents. Typically it is implemented by 109 | /// quad read command 0x6B 110 | /// @param addr address to read 111 | /// @param buffer buffer to hold data 112 | /// @param len number of byte to read 113 | /// @return true if success 114 | virtual bool readMemory(uint32_t addr, uint8_t *buffer, uint32_t len) = 0; 115 | 116 | /// Write data to external flash contents, flash sector must be previously 117 | /// erased first. Typically it uses quad write command 0x32 118 | /// @param addr address to read 119 | /// @param data writing data 120 | /// @param len number of byte to read 121 | /// @return true if success 122 | virtual bool writeMemory(uint32_t addr, uint8_t const *data, 123 | uint32_t len) = 0; 124 | 125 | void setAddressLength(uint8_t addr_len) { _addr_len = addr_len; } 126 | void setReadCommand(uint8_t cmd_read) { _cmd_read = cmd_read; } 127 | 128 | protected: 129 | // Number of bytes for address 130 | uint8_t _addr_len; 131 | 132 | // Command use for read operation 133 | uint8_t _cmd_read; 134 | }; 135 | 136 | #include "qspi/Adafruit_FlashTransport_QSPI.h" 137 | #include "spi/Adafruit_FlashTransport_SPI.h" 138 | 139 | #ifdef ARDUINO_ARCH_ESP32 140 | #include "esp32/Adafruit_FlashTransport_ESP32.h" 141 | #endif 142 | 143 | #ifdef ARDUINO_ARCH_RP2040 144 | #include "rp2040/Adafruit_FlashTransport_RP2040.h" 145 | #endif 146 | 147 | #endif /* ADAFRUIT_FLASHTRANSPORT_H_ */ 148 | -------------------------------------------------------------------------------- /src/Adafruit_SPIFlash.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 Ha Thach and Dean Miller for Adafruit Industries LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #include "Adafruit_SPIFlash.h" 26 | 27 | #ifdef USE_TINYUSB 28 | #include "Adafruit_TinyUSB.h" 29 | #endif 30 | 31 | #define LOGICAL_BLOCK_SIZE 512 32 | 33 | #if SPIFLASH_DEBUG 34 | #define SPIFLASH_LOG(_block, _count) \ 35 | do { \ 36 | Serial.print(__FUNCTION__); \ 37 | Serial.print(": lba = "); \ 38 | Serial.print(_block); \ 39 | if (_count) { \ 40 | Serial.print(" count = "); \ 41 | Serial.print(_count); \ 42 | } \ 43 | Serial.println(); \ 44 | } while (0) 45 | #else 46 | #define SPIFLASH_LOG(_sector, _count) 47 | #endif 48 | 49 | Adafruit_SPIFlash::Adafruit_SPIFlash() : Adafruit_SPIFlashBase() { 50 | _cache_en = true; 51 | _cache = NULL; 52 | } 53 | 54 | Adafruit_SPIFlash::Adafruit_SPIFlash(Adafruit_FlashTransport *transport, 55 | bool useCache) 56 | : Adafruit_SPIFlashBase(transport) { 57 | _cache_en = useCache; 58 | _cache = NULL; 59 | } 60 | 61 | bool Adafruit_SPIFlash::begin(SPIFlash_Device_t const *flash_devs, 62 | size_t count) { 63 | bool ret = Adafruit_SPIFlashBase::begin(flash_devs, count); 64 | 65 | #ifndef __AVR__ 66 | // Use cache if not FRAM 67 | // Note: Skip caching if AVR. Comment out since new cache on AVR seems to 68 | // corrupt memory rather than safely return NULL 69 | if (_flash_dev && !_flash_dev->is_fram) { 70 | if (_cache_en && !_cache) { 71 | _cache = new Adafruit_FlashCache; 72 | } 73 | } 74 | #endif 75 | 76 | return ret; 77 | } 78 | 79 | void Adafruit_SPIFlash::end(void) { 80 | // invoke base class end 81 | Adafruit_SPIFlashBase::end(); 82 | 83 | if (_cache != NULL) { 84 | delete _cache; 85 | _cache = NULL; 86 | } 87 | } 88 | 89 | //--------------------------------------------------------------------+ 90 | // SdFat BaseBlockDRiver API 91 | // A block is 512 bytes 92 | //--------------------------------------------------------------------+ 93 | 94 | bool Adafruit_SPIFlash::isBusy() { return !Adafruit_SPIFlashBase::isReady(); } 95 | 96 | uint32_t Adafruit_SPIFlash::sectorCount() { 97 | return Adafruit_SPIFlashBase::size() / LOGICAL_BLOCK_SIZE; 98 | } 99 | 100 | bool Adafruit_SPIFlash::readSector(uint32_t block, uint8_t *dst) { 101 | SPIFLASH_LOG(block, 1); 102 | 103 | if (_cache) { 104 | return _cache->read(this, block * LOGICAL_BLOCK_SIZE, dst, 105 | LOGICAL_BLOCK_SIZE); 106 | } else { 107 | // FRAM does not need caching 108 | return this->readBuffer(block * LOGICAL_BLOCK_SIZE, dst, 109 | LOGICAL_BLOCK_SIZE) > 0; 110 | } 111 | } 112 | 113 | bool Adafruit_SPIFlash::syncDevice() { 114 | SPIFLASH_LOG(0, 0); 115 | 116 | if (_cache) { 117 | return _cache->sync(this); 118 | } else { 119 | return true; 120 | } 121 | } 122 | 123 | bool Adafruit_SPIFlash::writeSector(uint32_t block, const uint8_t *src) { 124 | SPIFLASH_LOG(block, 1); 125 | 126 | if (_cache) { 127 | return _cache->write(this, block * LOGICAL_BLOCK_SIZE, src, 128 | LOGICAL_BLOCK_SIZE); 129 | } else { 130 | return this->writeBuffer(block * LOGICAL_BLOCK_SIZE, src, 131 | LOGICAL_BLOCK_SIZE) > 0; 132 | } 133 | } 134 | 135 | bool Adafruit_SPIFlash::readSectors(uint32_t block, uint8_t *dst, size_t nb) { 136 | SPIFLASH_LOG(block, nb); 137 | 138 | if (_cache) { 139 | return _cache->read(this, block * LOGICAL_BLOCK_SIZE, dst, 140 | LOGICAL_BLOCK_SIZE * nb); 141 | } else { 142 | return this->readBuffer(block * LOGICAL_BLOCK_SIZE, dst, 143 | LOGICAL_BLOCK_SIZE * nb) > 0; 144 | } 145 | } 146 | 147 | bool Adafruit_SPIFlash::writeSectors(uint32_t block, const uint8_t *src, 148 | size_t nb) { 149 | SPIFLASH_LOG(block, nb); 150 | if (_cache) { 151 | return _cache->write(this, block * LOGICAL_BLOCK_SIZE, src, 152 | LOGICAL_BLOCK_SIZE * nb); 153 | } else { 154 | return this->writeBuffer(block * LOGICAL_BLOCK_SIZE, src, 155 | LOGICAL_BLOCK_SIZE * nb) > 0; 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/spi/Adafruit_FlashTransport_SPI.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 hathach for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #include "Adafruit_FlashTransport.h" 26 | 27 | Adafruit_FlashTransport_SPI::Adafruit_FlashTransport_SPI( 28 | uint8_t ss, SPIClass *spiinterface) { 29 | _cmd_read = SFLASH_CMD_READ; 30 | _addr_len = 3; // work with most device if not set 31 | _ss = ss; 32 | _spi = spiinterface; 33 | _clock_wr = _clock_rd = 4000000; 34 | } 35 | 36 | Adafruit_FlashTransport_SPI::Adafruit_FlashTransport_SPI(uint8_t ss, 37 | SPIClass &spiinterface) 38 | : Adafruit_FlashTransport_SPI(ss, &spiinterface) {} 39 | 40 | void Adafruit_FlashTransport_SPI::begin(void) { 41 | pinMode(_ss, OUTPUT); 42 | digitalWrite(_ss, HIGH); 43 | 44 | _spi->begin(); 45 | } 46 | 47 | void Adafruit_FlashTransport_SPI::end(void) { 48 | _spi->end(); 49 | 50 | pinMode(_ss, INPUT); 51 | } 52 | 53 | void Adafruit_FlashTransport_SPI::setClockSpeed(uint32_t write_hz, 54 | uint32_t read_hz) { 55 | _clock_wr = write_hz; 56 | _clock_rd = read_hz; 57 | } 58 | 59 | bool Adafruit_FlashTransport_SPI::runCommand(uint8_t command) { 60 | beginTransaction(_clock_wr); 61 | 62 | _spi->transfer(command); 63 | 64 | endTransaction(); 65 | 66 | return true; 67 | } 68 | 69 | bool Adafruit_FlashTransport_SPI::readCommand(uint8_t command, 70 | uint8_t *response, uint32_t len) { 71 | beginTransaction(_clock_rd); 72 | 73 | _spi->transfer(command); 74 | while (len--) { 75 | *response++ = _spi->transfer(0xFF); 76 | } 77 | 78 | endTransaction(); 79 | 80 | return true; 81 | } 82 | 83 | bool Adafruit_FlashTransport_SPI::writeCommand(uint8_t command, 84 | uint8_t const *data, 85 | uint32_t len) { 86 | beginTransaction(_clock_wr); 87 | 88 | _spi->transfer(command); 89 | while (len--) { 90 | (void)_spi->transfer(*data++); 91 | } 92 | 93 | endTransaction(); 94 | 95 | return true; 96 | } 97 | 98 | bool Adafruit_FlashTransport_SPI::eraseCommand(uint8_t command, uint32_t addr) { 99 | beginTransaction(_clock_wr); 100 | 101 | uint8_t cmd_with_addr[5] = {command}; 102 | fillAddress(cmd_with_addr + 1, addr); 103 | 104 | _spi->transfer(cmd_with_addr, 1 + _addr_len); 105 | 106 | endTransaction(); 107 | 108 | return true; 109 | } 110 | 111 | void Adafruit_FlashTransport_SPI::fillAddress(uint8_t *buf, uint32_t addr) { 112 | switch (_addr_len) { 113 | case 4: 114 | *buf++ = (addr >> 24) & 0xFF; 115 | //__attribute__((fallthrough)); ESP32 doesn't support this attribute yet 116 | // fall through 117 | 118 | case 3: 119 | *buf++ = (addr >> 16) & 0xFF; 120 | //__attribute__((fallthrough)); ESP32 doesn't support this attribute yet 121 | // fall through 122 | 123 | case 2: 124 | default: 125 | *buf++ = (addr >> 8) & 0xFF; 126 | *buf++ = addr & 0xFF; 127 | } 128 | } 129 | 130 | bool Adafruit_FlashTransport_SPI::readMemory(uint32_t addr, uint8_t *data, 131 | uint32_t len) { 132 | beginTransaction(_clock_rd); 133 | 134 | uint8_t cmd_with_addr[6] = {_cmd_read}; 135 | fillAddress(cmd_with_addr + 1, addr); 136 | 137 | // Fast Read has 1 extra dummy byte 138 | uint8_t const cmd_len = 139 | 1 + _addr_len + (SFLASH_CMD_FAST_READ == _cmd_read ? 1 : 0); 140 | 141 | _spi->transfer(cmd_with_addr, cmd_len); 142 | 143 | // Use SPI DMA if available for best performance 144 | #if defined(ARDUINO_NRF52_ADAFRUIT) && defined(NRF52840_XXAA) 145 | _spi->transfer(NULL, data, len); 146 | #elif defined(ARDUINO_ARCH_SAMD) && defined(_ADAFRUIT_ZERODMA_H_) 147 | _spi->transfer(NULL, data, len, true); 148 | #else 149 | _spi->transfer(data, len); 150 | #endif 151 | 152 | endTransaction(); 153 | 154 | return true; 155 | } 156 | 157 | bool Adafruit_FlashTransport_SPI::writeMemory(uint32_t addr, 158 | uint8_t const *data, 159 | uint32_t len) { 160 | beginTransaction(_clock_wr); 161 | 162 | uint8_t cmd_with_addr[5] = {SFLASH_CMD_PAGE_PROGRAM}; 163 | fillAddress(cmd_with_addr + 1, addr); 164 | 165 | _spi->transfer(cmd_with_addr, 1 + _addr_len); 166 | 167 | // Use SPI DMA if available for best performance 168 | #if defined(ARDUINO_NRF52_ADAFRUIT) && defined(NRF52840_XXAA) 169 | _spi->transfer(data, NULL, len); 170 | #elif defined(ARDUINO_ARCH_SAMD) && defined(_ADAFRUIT_ZERODMA_H_) 171 | _spi->transfer(data, NULL, len, true); 172 | #else 173 | while (len--) { 174 | _spi->transfer(*data++); 175 | } 176 | #endif 177 | 178 | endTransaction(); 179 | 180 | return true; 181 | } 182 | -------------------------------------------------------------------------------- /examples/flash_manipulator/flash_manipulator.ino: -------------------------------------------------------------------------------- 1 | /* This is my go-to example for erasing, dumping, writing and verifying SPI 2 | * flash! */ 3 | 4 | #include "SdFat_Adafruit_Fork.h" 5 | #include 6 | 7 | #include 8 | 9 | // for flashTransport definition 10 | #include "flash_config.h" 11 | 12 | Adafruit_SPIFlash flash(&flashTransport); 13 | 14 | // file system on SD card 15 | SdFat sd; 16 | 17 | #define SD_CS 10 18 | #define MAXPAGESIZE 256 19 | 20 | File32 dataFile; 21 | uint8_t buffer[MAXPAGESIZE], buffer2[MAXPAGESIZE]; 22 | uint32_t results; 23 | 24 | void error(const char *str) { 25 | Serial.println(str); 26 | while (1) { 27 | delay(1); 28 | } 29 | } 30 | 31 | void setup(void) { 32 | Serial.begin(115200); 33 | while (!Serial) { 34 | delay(1); 35 | } 36 | 37 | flash.begin(); 38 | 39 | Serial.println(F("Adafruit Serial Flash Manipulator example")); 40 | Serial.print(F("JEDEC ID: ")); 41 | Serial.println(flash.getJEDECID(), HEX); 42 | Serial.print(F("Flash size: ")); 43 | Serial.println(flash.size()); 44 | 45 | Serial.print("Initializing SD card... "); 46 | // see if the card is present and can be initialized: 47 | if (!sd.begin(SD_CS, SD_SCK_MHZ(50))) { 48 | Serial.println("Card failed, or not present"); 49 | // don't do anything more: 50 | while (1) { 51 | delay(1); 52 | } 53 | } 54 | 55 | Serial.println("OK"); 56 | } 57 | 58 | void loop(void) { 59 | while (Serial.available()) { 60 | Serial.read(); 61 | } 62 | Serial.println(F("FLASH DUMPER - Hello! Press E (rase), W (rite), V (erify), " 63 | "or D (ump) to begin")); 64 | 65 | while (!Serial.available()) 66 | ; 67 | char cmd = toupper(Serial.read()); 68 | 69 | uint16_t pagesize = flash.pageSize(); 70 | Serial.print(F("Page size: ")); 71 | Serial.println(pagesize); 72 | 73 | if (cmd == 'D') { 74 | // open the file. note that only one file can be open at a time, 75 | // so you have to close this one before opening another. 76 | // Open up the file we're going to log to! 77 | dataFile = sd.open(F("flshdump.bin"), FILE_WRITE); 78 | if (!dataFile) { 79 | error("error opening flshdump.bin"); 80 | } 81 | 82 | Serial.println(F("Dumping FLASH to disk")); 83 | for (uint32_t page = 0; page < flash.numPages(); page++) { 84 | memset(buffer, 0, pagesize); 85 | Serial.print(F("// Reading page ")); 86 | Serial.println(page); 87 | uint16_t r = flash.readBuffer(page * pagesize, buffer, pagesize); 88 | // Serial.print(r); Serial.print(' '); PrintHex(buffer, r); 89 | dataFile.write(buffer, r); 90 | } 91 | dataFile.flush(); 92 | dataFile.close(); 93 | } 94 | if (cmd == 'E') { 95 | Serial.println(F("Erasing chip")); 96 | flash.eraseChip(); 97 | } 98 | if (cmd == 'V') { 99 | dataFile = sd.open("flshdump.bin", FILE_READ); 100 | if (!dataFile) { 101 | error("error opening flshdump.bin"); 102 | } 103 | Serial.println(F("Verifying FLASH from disk")); 104 | for (uint32_t page = 0; page < flash.numPages(); page++) { 105 | memset(buffer, 0, pagesize); 106 | memset(buffer2, 0, pagesize); 107 | 108 | Serial.print(F("// Verifying page ")); 109 | Serial.println(page); 110 | 111 | uint32_t r = flash.readBuffer(page * pagesize, buffer, pagesize); 112 | if (r != pagesize) { 113 | error("Flash read failure"); 114 | } 115 | 116 | if (r != (uint32_t)dataFile.read(buffer2, r)) { 117 | error("SD read failure"); 118 | } 119 | 120 | if (memcmp(buffer, buffer2, r) != 0) { 121 | PrintHex(buffer, r); 122 | PrintHex(buffer2, r); 123 | Serial.println(F("verification failed")); 124 | return; 125 | } 126 | } 127 | Serial.println(F("Done!")); 128 | dataFile.close(); 129 | } 130 | 131 | if (cmd == 'W') { 132 | dataFile = sd.open("flshdump.bin", FILE_READ); 133 | if (!dataFile) { 134 | error("error opening flshdump.bin"); 135 | } 136 | 137 | Serial.println(F("Writing FLASH from disk")); 138 | for (uint32_t page = 0; page < flash.numPages(); page++) { 139 | memset(buffer, 0, pagesize); 140 | 141 | int16_t r = dataFile.read(buffer, pagesize); 142 | if (r == 0) 143 | break; 144 | Serial.print(F("// Writing page ")); 145 | Serial.println(page); 146 | 147 | if (r != (int)flash.writeBuffer(page * r, buffer, r)) { 148 | error("Flash write failure"); 149 | } 150 | } 151 | Serial.println(("Done!")); 152 | dataFile.close(); 153 | } 154 | } 155 | 156 | /**************************************************************************/ 157 | /*! 158 | @brief Prints a hexadecimal value in plain characters, along with 159 | the char equivalents in the following format: 160 | 161 | 00 00 00 00 00 00 ...... 162 | 163 | @param data Pointer to the byte data 164 | @param numBytes Data length in bytes 165 | */ 166 | /**************************************************************************/ 167 | void PrintHexChar(const byte *data, const uint32_t numBytes) { 168 | uint32_t szPos; 169 | for (szPos = 0; szPos < numBytes; szPos++) { 170 | // Append leading 0 for small values 171 | if (data[szPos] <= 0xF) 172 | Serial.print(F("0")); 173 | Serial.print(data[szPos], HEX); 174 | if ((numBytes > 1) && (szPos != numBytes - 1)) { 175 | Serial.print(F(" ")); 176 | } 177 | } 178 | Serial.print(F(" ")); 179 | for (szPos = 0; szPos < numBytes; szPos++) { 180 | if (data[szPos] <= 0x1F) 181 | Serial.print('.'); 182 | else 183 | Serial.write(data[szPos]); 184 | } 185 | Serial.println(""); 186 | } 187 | 188 | /**************************************************************************/ 189 | /*! 190 | @brief Prints a hexadecimal value in plain characters 191 | 192 | @param data Pointer to the byte data 193 | @param numBytes Data length in bytes 194 | */ 195 | /**************************************************************************/ 196 | void PrintHex(const byte *data, const uint32_t numBytes) { 197 | uint32_t szPos; 198 | for (szPos = 0; szPos < numBytes; szPos++) { 199 | Serial.print(F("0x")); 200 | // Append leading 0 for small values 201 | if (data[szPos] <= 0xF) 202 | Serial.print(F("0")); 203 | Serial.print(data[szPos], HEX); 204 | if ((numBytes > 1) && (szPos != numBytes - 1)) { 205 | Serial.print(F(" ")); 206 | } 207 | } 208 | Serial.println(""); 209 | } 210 | -------------------------------------------------------------------------------- /examples/SdFat_format/SdFat_format.ino: -------------------------------------------------------------------------------- 1 | // Adafruit SPI Flash FatFs Format Example 2 | // Author: Tony DiCola 3 | // 4 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 5 | // !! NOTE: YOU WILL ERASE ALL DATA BY RUNNING THIS SKETCH! !! 6 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 7 | // 8 | // Usage: 9 | // - Modify the pins and type of fatfs object in the config 10 | // section below if necessary (usually not necessary). 11 | // - Upload this sketch to your M0 express board. 12 | // - Open the serial monitor at 115200 baud. You should see a 13 | // prompt to confirm formatting. If you don't see the prompt 14 | // close the serial monitor, press the board reset button, 15 | // wait a few seconds, then open the serial monitor again. 16 | // - Type OK and enter to confirm the format when prompted. 17 | // - Partitioning and formatting will take about 30-60 seconds. 18 | // Once formatted a message will be printed to notify you that 19 | // it is finished. 20 | // 21 | #include "SdFat_Adafruit_Fork.h" 22 | #include 23 | #include 24 | 25 | // Since SdFat doesn't fully support FAT12 such as format a new flash 26 | // We will use Elm Cham's fatfs f_mkfs() to format 27 | #include "ff.h" 28 | #include "diskio.h" 29 | 30 | // up to 11 characters 31 | #define DISK_LABEL "EXT FLASH" 32 | 33 | // for flashTransport definition 34 | #include "flash_config.h" 35 | 36 | Adafruit_SPIFlash flash(&flashTransport); 37 | FatVolume fatfs; 38 | 39 | void format_fat12(void) { 40 | // Working buffer for f_mkfs. 41 | #ifdef __AVR__ 42 | uint8_t workbuf[512]; 43 | #else 44 | uint8_t workbuf[4096]; 45 | #endif 46 | 47 | // Elm Cham's fatfs objects 48 | FATFS elmchamFatfs; 49 | 50 | // Make filesystem. 51 | FRESULT r = f_mkfs("", FM_FAT, 0, workbuf, sizeof(workbuf)); 52 | if (r != FR_OK) { 53 | Serial.print(F("Error, f_mkfs failed with error code: ")); 54 | Serial.println(r, DEC); 55 | while (1) 56 | yield(); 57 | } 58 | 59 | // mount to set disk label 60 | r = f_mount(&elmchamFatfs, "0:", 1); 61 | if (r != FR_OK) { 62 | Serial.print(F("Error, f_mount failed with error code: ")); 63 | Serial.println(r, DEC); 64 | while (1) 65 | yield(); 66 | } 67 | 68 | // Setting label 69 | Serial.println(F("Setting disk label to: " DISK_LABEL)); 70 | r = f_setlabel(DISK_LABEL); 71 | if (r != FR_OK) { 72 | Serial.print(F("Error, f_setlabel failed with error code: ")); 73 | Serial.println(r, DEC); 74 | while (1) 75 | yield(); 76 | } 77 | 78 | // unmount 79 | f_unmount("0:"); 80 | 81 | // sync to make sure all data is written to flash 82 | flash.syncBlocks(); 83 | 84 | Serial.println(F("Formatted flash!")); 85 | } 86 | 87 | void check_fat12(void) { 88 | // Check new filesystem 89 | if (!fatfs.begin(&flash)) { 90 | Serial.println(F("Error, failed to mount newly formatted filesystem!")); 91 | while (1) 92 | delay(1); 93 | } 94 | } 95 | 96 | void setup() { 97 | // Initialize serial port and wait for it to open before continuing. 98 | Serial.begin(115200); 99 | while (!Serial) 100 | delay(100); 101 | 102 | Serial.println(F("Adafruit SPI Flash FatFs Format Example")); 103 | 104 | // Initialize flash library and check its chip ID. 105 | if (!flash.begin()) { 106 | Serial.println(F("Error, failed to initialize flash chip!")); 107 | while (1) 108 | yield(); 109 | } 110 | 111 | Serial.print(F("Flash chip JEDEC ID: 0x")); 112 | Serial.println(flash.getJEDECID(), HEX); 113 | Serial.print(F("Flash size: ")); 114 | Serial.print(flash.size() / 1024); 115 | Serial.println(F(" KB")); 116 | 117 | // Uncomment to flash LED while writing to flash 118 | // flash.setIndicator(LED_BUILTIN, true); 119 | 120 | // Wait for user to send OK to continue. 121 | Serial.setTimeout( 122 | 30000); // Increase timeout to print message less frequently. 123 | do { 124 | Serial.println(F("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" 125 | "!!!!!!!!!!!!")); 126 | Serial.println(F("This sketch will ERASE ALL DATA on the flash chip and " 127 | "format it with a new filesystem!")); 128 | Serial.println(F("Type OK (all caps) and press enter to continue.")); 129 | Serial.println(F("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" 130 | "!!!!!!!!!!!!")); 131 | } while (!Serial.find((char *)"OK")); 132 | 133 | // Call fatfs begin and passed flash object to initialize file system 134 | Serial.println( 135 | F("Creating and formatting FAT filesystem (this takes ~60 seconds)...")); 136 | 137 | format_fat12(); 138 | 139 | check_fat12(); 140 | 141 | // Done! 142 | Serial.println( 143 | F("Flash chip successfully formatted with new empty filesystem!")); 144 | } 145 | 146 | void loop() { 147 | // Nothing to be done in the main loop. 148 | } 149 | 150 | //--------------------------------------------------------------------+ 151 | // fatfs diskio 152 | //--------------------------------------------------------------------+ 153 | extern "C" { 154 | 155 | DSTATUS disk_status(BYTE pdrv) { 156 | (void)pdrv; 157 | return 0; 158 | } 159 | 160 | DSTATUS disk_initialize(BYTE pdrv) { 161 | (void)pdrv; 162 | return 0; 163 | } 164 | 165 | DRESULT disk_read(BYTE pdrv, /* Physical drive nmuber to identify the drive */ 166 | BYTE *buff, /* Data buffer to store read data */ 167 | DWORD sector, /* Start sector in LBA */ 168 | UINT count /* Number of sectors to read */ 169 | ) { 170 | (void)pdrv; 171 | return flash.readBlocks(sector, buff, count) ? RES_OK : RES_ERROR; 172 | } 173 | 174 | DRESULT disk_write(BYTE pdrv, /* Physical drive nmuber to identify the drive */ 175 | const BYTE *buff, /* Data to be written */ 176 | DWORD sector, /* Start sector in LBA */ 177 | UINT count /* Number of sectors to write */ 178 | ) { 179 | (void)pdrv; 180 | return flash.writeBlocks(sector, buff, count) ? RES_OK : RES_ERROR; 181 | } 182 | 183 | DRESULT disk_ioctl(BYTE pdrv, /* Physical drive nmuber (0..) */ 184 | BYTE cmd, /* Control code */ 185 | void *buff /* Buffer to send/receive control data */ 186 | ) { 187 | (void)pdrv; 188 | 189 | switch (cmd) { 190 | case CTRL_SYNC: 191 | flash.syncBlocks(); 192 | return RES_OK; 193 | 194 | case GET_SECTOR_COUNT: 195 | *((DWORD *)buff) = flash.size() / 512; 196 | return RES_OK; 197 | 198 | case GET_SECTOR_SIZE: 199 | *((WORD *)buff) = 512; 200 | return RES_OK; 201 | 202 | case GET_BLOCK_SIZE: 203 | *((DWORD *)buff) = 8; // erase block size in units of sector size 204 | return RES_OK; 205 | 206 | default: 207 | return RES_PARERR; 208 | } 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/rp2040/Adafruit_FlashTransport_RP2040.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2020 hathach for Adafruit Industries 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #include "Adafruit_FlashTransport.h" 26 | 27 | #ifdef ARDUINO_ARCH_RP2040 28 | 29 | #include 30 | 31 | // symbol from linker that matches 'Tools->Flash Size' menu selection for 32 | // filesystem 33 | extern uint8_t _FS_start; 34 | extern uint8_t _FS_end; 35 | 36 | // FS Size determined by menu selection 37 | #define MENU_FS_SIZE ((uint32_t)(&_FS_end - &_FS_start)) 38 | 39 | // CircuitPython partition scheme with 40 | // - start address = 1 MB (Pico), 1.5 MB (Pico W) 41 | // - size = total flash - 1 MB + 4KB (since CPY does not reserve EEPROM from 42 | // arduino core) 43 | #if defined(ARDUINO_RASPBERRY_PI_PICO_W) 44 | const uint32_t Adafruit_FlashTransport_RP2040::CPY_START_ADDR = (1536 * 1024); 45 | #else 46 | const uint32_t Adafruit_FlashTransport_RP2040::CPY_START_ADDR = 47 | (1 * 1024 * 1024); 48 | #endif 49 | const uint32_t Adafruit_FlashTransport_RP2040::CPY_SIZE = 50 | (((uint32_t)&_FS_end) - 51 | (XIP_BASE + Adafruit_FlashTransport_RP2040::CPY_START_ADDR) + 4096); 52 | 53 | static inline void fl_lock(bool idle) { 54 | noInterrupts(); 55 | if (idle) 56 | rp2040.idleOtherCore(); 57 | } 58 | 59 | static inline void fl_unlock(bool idle) { 60 | if (idle) 61 | rp2040.resumeOtherCore(); 62 | interrupts(); 63 | } 64 | 65 | Adafruit_FlashTransport_RP2040::Adafruit_FlashTransport_RP2040( 66 | uint32_t start_addr, uint32_t size, bool idle) 67 | : _idle_other_core_on_write(idle) { 68 | _cmd_read = SFLASH_CMD_READ; 69 | _addr_len = 3; // work with most device if not set 70 | 71 | _start_addr = start_addr; 72 | _size = size; 73 | 74 | // detect start address and size that match menu option 75 | if (!_start_addr) { 76 | _start_addr = (uint32_t)&_FS_start - XIP_BASE; 77 | } 78 | 79 | if (!_size) { 80 | _size = MENU_FS_SIZE; 81 | } 82 | 83 | memset(&_flash_dev, 0, sizeof(_flash_dev)); 84 | } 85 | 86 | void Adafruit_FlashTransport_RP2040::begin(void) { 87 | _flash_dev.total_size = _size; 88 | 89 | // Read the RDID register only for JEDEC ID 90 | uint8_t const cmd[] = { 91 | 0x9f, 92 | 0, 93 | 0, 94 | 0, 95 | }; 96 | uint8_t data[4]; 97 | fl_lock(_idle_other_core_on_write); 98 | flash_do_cmd(cmd, data, 4); 99 | fl_unlock(_idle_other_core_on_write); 100 | 101 | uint8_t *jedec_ids = data + 1; 102 | 103 | _flash_dev.manufacturer_id = jedec_ids[0]; 104 | _flash_dev.memory_type = jedec_ids[1]; 105 | _flash_dev.capacity = jedec_ids[2]; 106 | } 107 | 108 | void Adafruit_FlashTransport_RP2040::end(void) { 109 | _cmd_read = SFLASH_CMD_READ; 110 | _addr_len = 3; // work with most device if not set 111 | } 112 | 113 | SPIFlash_Device_t *Adafruit_FlashTransport_RP2040::getFlashDevice(void) { 114 | return &_flash_dev; 115 | } 116 | 117 | void Adafruit_FlashTransport_RP2040::setClockSpeed(uint32_t write_hz, 118 | uint32_t read_hz) { 119 | // do nothing, just use current configured clock 120 | (void)write_hz; 121 | (void)read_hz; 122 | } 123 | 124 | bool Adafruit_FlashTransport_RP2040::runCommand(uint8_t command) { 125 | if (_size < 4096) { 126 | return false; 127 | } 128 | 129 | switch (command) { 130 | case SFLASH_CMD_ERASE_CHIP: 131 | fl_lock(_idle_other_core_on_write); 132 | flash_range_erase(_start_addr, _size); 133 | fl_unlock(_idle_other_core_on_write); 134 | break; 135 | 136 | // do nothing, mostly write enable 137 | default: 138 | break; 139 | } 140 | 141 | return true; 142 | } 143 | 144 | bool Adafruit_FlashTransport_RP2040::readCommand(uint8_t command, 145 | uint8_t *response, 146 | uint32_t len) { 147 | // mostly is Read STATUS, just fill with 0x0 148 | (void)command; 149 | memset(response, 0, len); 150 | 151 | return true; 152 | } 153 | 154 | bool Adafruit_FlashTransport_RP2040::writeCommand(uint8_t command, 155 | uint8_t const *data, 156 | uint32_t len) { 157 | // mostly is Write Status, do nothing 158 | (void)command; 159 | (void)data; 160 | (void)len; 161 | 162 | return true; 163 | } 164 | 165 | bool Adafruit_FlashTransport_RP2040::eraseCommand(uint8_t command, 166 | uint32_t addr) { 167 | uint32_t erase_sz; 168 | 169 | if (command == SFLASH_CMD_ERASE_SECTOR) { 170 | erase_sz = SFLASH_SECTOR_SIZE; 171 | } else if (command == SFLASH_CMD_ERASE_BLOCK) { 172 | erase_sz = SFLASH_BLOCK_SIZE; 173 | } else { 174 | return false; 175 | } 176 | 177 | if (!check_addr(addr + erase_sz)) { 178 | return false; 179 | } 180 | 181 | fl_lock(_idle_other_core_on_write); 182 | flash_range_erase(_start_addr + addr, erase_sz); 183 | fl_unlock(_idle_other_core_on_write); 184 | 185 | return true; 186 | } 187 | 188 | bool Adafruit_FlashTransport_RP2040::readMemory(uint32_t addr, uint8_t *data, 189 | uint32_t len) { 190 | if (!check_addr(addr + len)) { 191 | return false; 192 | } 193 | 194 | memcpy(data, (void *)(XIP_BASE + _start_addr + addr), len); 195 | return true; 196 | } 197 | 198 | bool Adafruit_FlashTransport_RP2040::writeMemory(uint32_t addr, 199 | uint8_t const *data, 200 | uint32_t len) { 201 | if (!check_addr(addr + len)) { 202 | return false; 203 | } 204 | 205 | fl_lock(_idle_other_core_on_write); 206 | flash_range_program(_start_addr + addr, data, len); 207 | fl_unlock(_idle_other_core_on_write); 208 | return true; 209 | } 210 | 211 | #endif 212 | -------------------------------------------------------------------------------- /src/qspi/Adafruit_FlashTransport_QSPI_SAMD.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 Ha Thach and Dean Miller for Adafruit Industries LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifdef __SAMD51__ 25 | 26 | #include "Adafruit_FlashTransport.h" 27 | #include "wiring_private.h" 28 | #include 29 | 30 | static void _run_instruction(uint8_t command, uint32_t iframe, uint32_t addr, 31 | uint8_t *buffer, uint32_t size); 32 | 33 | // Turn off cache and invalidate all data in it. 34 | static void samd_peripherals_disable_and_clear_cache(void) { 35 | CMCC->CTRL.bit.CEN = 0; 36 | while (CMCC->SR.bit.CSTS) { 37 | } 38 | CMCC->MAINT0.bit.INVALL = 1; 39 | } 40 | 41 | // Enable cache 42 | static void samd_peripherals_enable_cache(void) { CMCC->CTRL.bit.CEN = 1; } 43 | 44 | Adafruit_FlashTransport_QSPI::Adafruit_FlashTransport_QSPI(void) 45 | : Adafruit_FlashTransport_QSPI(PIN_QSPI_SCK, PIN_QSPI_CS, PIN_QSPI_IO0, 46 | PIN_QSPI_IO1, PIN_QSPI_IO2, PIN_QSPI_IO3) {} 47 | 48 | Adafruit_FlashTransport_QSPI::Adafruit_FlashTransport_QSPI( 49 | int8_t sck, int8_t cs, int8_t io0, int8_t io1, int8_t io2, int8_t io3) { 50 | _addr_len = 3; // work with most device if not set 51 | _cmd_read = SFLASH_CMD_QUAD_READ; 52 | _sck = sck; 53 | _cs = cs; 54 | _io0 = io0; 55 | _io1 = io1; 56 | _io2 = io2; 57 | _io3 = io3; 58 | } 59 | 60 | void Adafruit_FlashTransport_QSPI::begin(void) { 61 | MCLK->APBCMASK.bit.QSPI_ = true; 62 | MCLK->AHBMASK.bit.QSPI_ = true; 63 | MCLK->AHBMASK.bit.QSPI_2X_ = false; // Only true if we are doing DDR. 64 | 65 | QSPI->CTRLA.bit.SWRST = 1; 66 | 67 | // set all pins to QSPI periph 68 | pinPeripheral(_sck, PIO_COM); 69 | pinPeripheral(_cs, PIO_COM); 70 | pinPeripheral(_io0, PIO_COM); 71 | pinPeripheral(_io1, PIO_COM); 72 | pinPeripheral(_io2, PIO_COM); 73 | pinPeripheral(_io3, PIO_COM); 74 | 75 | QSPI->BAUD.reg = 76 | QSPI_BAUD_BAUD(VARIANT_MCK / 4000000UL); // start with low 4Mhz, Mode 0 77 | QSPI->CTRLB.reg = QSPI_CTRLB_MODE_MEMORY | QSPI_CTRLB_DATALEN_8BITS | 78 | QSPI_CTRLB_CSMODE_LASTXFER; 79 | 80 | QSPI->CTRLA.bit.ENABLE = 1; 81 | } 82 | 83 | void Adafruit_FlashTransport_QSPI::end(void) { 84 | QSPI->CTRLA.bit.ENABLE = 0; 85 | 86 | MCLK->APBCMASK.bit.QSPI_ = false; 87 | MCLK->AHBMASK.bit.QSPI_ = false; 88 | MCLK->AHBMASK.bit.QSPI_2X_ = false; 89 | } 90 | 91 | bool Adafruit_FlashTransport_QSPI::runCommand(uint8_t command) { 92 | uint32_t iframe = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI | 93 | QSPI_INSTRFRAME_ADDRLEN_24BITS | 94 | QSPI_INSTRFRAME_TFRTYPE_READ | QSPI_INSTRFRAME_INSTREN; 95 | 96 | _run_instruction(command, iframe, 0, NULL, 0); 97 | return true; 98 | } 99 | 100 | bool Adafruit_FlashTransport_QSPI::readCommand(uint8_t command, 101 | uint8_t *response, 102 | uint32_t len) { 103 | uint32_t iframe = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI | 104 | QSPI_INSTRFRAME_ADDRLEN_24BITS | 105 | QSPI_INSTRFRAME_TFRTYPE_READ | QSPI_INSTRFRAME_INSTREN | 106 | QSPI_INSTRFRAME_DATAEN; 107 | 108 | samd_peripherals_disable_and_clear_cache(); 109 | _run_instruction(command, iframe, 0, response, len); 110 | samd_peripherals_enable_cache(); 111 | 112 | return true; 113 | } 114 | 115 | bool Adafruit_FlashTransport_QSPI::writeCommand(uint8_t command, 116 | uint8_t const *data, 117 | uint32_t len) { 118 | uint32_t iframe = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI | 119 | QSPI_INSTRFRAME_ADDRLEN_24BITS | 120 | QSPI_INSTRFRAME_TFRTYPE_WRITE | QSPI_INSTRFRAME_INSTREN | 121 | (data != NULL ? QSPI_INSTRFRAME_DATAEN : 0); 122 | 123 | samd_peripherals_disable_and_clear_cache(); 124 | _run_instruction(command, iframe, 0, (uint8_t *)data, len); 125 | samd_peripherals_enable_cache(); 126 | 127 | return true; 128 | } 129 | 130 | bool Adafruit_FlashTransport_QSPI::eraseCommand(uint8_t command, 131 | uint32_t address) { 132 | // Sector Erase 133 | uint32_t iframe = QSPI_INSTRFRAME_WIDTH_SINGLE_BIT_SPI | 134 | QSPI_INSTRFRAME_ADDRLEN_24BITS | 135 | QSPI_INSTRFRAME_TFRTYPE_WRITE | QSPI_INSTRFRAME_INSTREN | 136 | QSPI_INSTRFRAME_ADDREN; 137 | 138 | _run_instruction(command, iframe, address, NULL, 0); 139 | return true; 140 | } 141 | 142 | bool Adafruit_FlashTransport_QSPI::readMemory(uint32_t addr, uint8_t *data, 143 | uint32_t len) { 144 | // Command 0x6B 1 line address, 4 line Data 145 | // Quad output mode, read memory type 146 | uint32_t iframe = QSPI_INSTRFRAME_WIDTH_QUAD_OUTPUT | 147 | QSPI_INSTRFRAME_ADDRLEN_24BITS | 148 | QSPI_INSTRFRAME_TFRTYPE_READMEMORY | 149 | QSPI_INSTRFRAME_INSTREN | QSPI_INSTRFRAME_ADDREN | 150 | QSPI_INSTRFRAME_DATAEN | QSPI_INSTRFRAME_DUMMYLEN(8); 151 | 152 | samd_peripherals_disable_and_clear_cache(); 153 | _run_instruction(SFLASH_CMD_QUAD_READ, iframe, addr, data, len); 154 | samd_peripherals_enable_cache(); 155 | 156 | return true; 157 | } 158 | 159 | bool Adafruit_FlashTransport_QSPI::writeMemory(uint32_t addr, 160 | uint8_t const *data, 161 | uint32_t len) { 162 | uint32_t iframe = 163 | QSPI_INSTRFRAME_WIDTH_QUAD_OUTPUT | QSPI_INSTRFRAME_ADDRLEN_24BITS | 164 | QSPI_INSTRFRAME_TFRTYPE_WRITEMEMORY | QSPI_INSTRFRAME_INSTREN | 165 | QSPI_INSTRFRAME_ADDREN | QSPI_INSTRFRAME_DATAEN; 166 | 167 | samd_peripherals_disable_and_clear_cache(); 168 | _run_instruction(SFLASH_CMD_QUAD_PAGE_PROGRAM, iframe, addr, (uint8_t *)data, 169 | len); 170 | samd_peripherals_enable_cache(); 171 | 172 | return true; 173 | } 174 | 175 | /**************************************************************************/ 176 | /*! 177 | @brief set the clock speed 178 | @param clock_hz clock speed in hertz 179 | */ 180 | /**************************************************************************/ 181 | void Adafruit_FlashTransport_QSPI::setClockSpeed(uint32_t clock_hz, 182 | uint32_t read_hz) { 183 | (void)read_hz; 184 | QSPI->BAUD.bit.BAUD = VARIANT_MCK / clock_hz; 185 | } 186 | 187 | /**************************************************************************/ 188 | /*! 189 | @brief Run a single QSPI instruction. 190 | @param command instruction code 191 | @param iframe iframe register value (configured by caller according to command 192 | code) 193 | @param addr the address to read or write from. If the instruction doesn't 194 | require an address, this parameter is meaningless. 195 | @param buffer pointer to the data to be written or stored depending on the type 196 | is Read or Write 197 | @param size the number of bytes to read or write. 198 | */ 199 | /**************************************************************************/ 200 | static void _run_instruction(uint8_t command, uint32_t iframe, uint32_t addr, 201 | uint8_t *buffer, uint32_t size) { 202 | if (command == SFLASH_CMD_ERASE_SECTOR || command == SFLASH_CMD_ERASE_BLOCK) { 203 | QSPI->INSTRADDR.reg = addr; 204 | } 205 | 206 | QSPI->INSTRCTRL.bit.INSTR = command; 207 | QSPI->INSTRFRAME.reg = iframe; 208 | 209 | // Dummy read of INSTRFRAME needed to synchronize. 210 | // See Instruction Transmission Flow Diagram, figure 37.9, page 995 211 | // and Example 4, page 998, section 37.6.8.5. 212 | volatile uint32_t dummy = QSPI->INSTRFRAME.reg; 213 | (void)dummy; 214 | 215 | if (buffer && size) { 216 | uint8_t *qspi_mem = (uint8_t *)(QSPI_AHB + addr); 217 | uint32_t const tfr_type = iframe & QSPI_INSTRFRAME_TFRTYPE_Msk; 218 | 219 | if ((tfr_type == QSPI_INSTRFRAME_TFRTYPE_READ) || 220 | (tfr_type == QSPI_INSTRFRAME_TFRTYPE_READMEMORY)) { 221 | memcpy(buffer, qspi_mem, size); 222 | } else { 223 | memcpy(qspi_mem, buffer, size); 224 | } 225 | } 226 | 227 | QSPI->CTRLA.reg = QSPI_CTRLA_ENABLE | QSPI_CTRLA_LASTXFER; 228 | 229 | while (!QSPI->INTFLAG.bit.INSTREND) { 230 | yield(); 231 | } 232 | QSPI->INTFLAG.bit.INSTREND = 1; 233 | } 234 | 235 | #endif 236 | -------------------------------------------------------------------------------- /src/qspi/Adafruit_FlashTransport_QSPI_NRF.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 Ha Thach for Adafruit Industries LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifdef NRF52840_XXAA 26 | 27 | #include "Adafruit_FlashTransport.h" 28 | #include "nrfx_qspi.h" 29 | #include 30 | 31 | // default PIN_QSPI_SCK, CS, IO0, IO1, IO2, IO3 to -1 to build with non-qpsi 32 | // board 33 | #ifndef PIN_QSPI_SCK 34 | #define PIN_QSPI_SCK -1 35 | #endif 36 | 37 | #ifndef PIN_QSPI_CS 38 | #define PIN_QSPI_CS -1 39 | #endif 40 | 41 | #ifndef PIN_QSPI_IO0 42 | #define PIN_QSPI_IO0 -1 43 | #endif 44 | 45 | #ifndef PIN_QSPI_IO1 46 | #define PIN_QSPI_IO1 -1 47 | #endif 48 | 49 | #ifndef PIN_QSPI_IO2 50 | #define PIN_QSPI_IO2 -1 51 | #endif 52 | 53 | #ifndef PIN_QSPI_IO3 54 | #define PIN_QSPI_IO3 -1 55 | #endif 56 | 57 | Adafruit_FlashTransport_QSPI::Adafruit_FlashTransport_QSPI(void) 58 | : Adafruit_FlashTransport_QSPI(PIN_QSPI_SCK, PIN_QSPI_CS, PIN_QSPI_IO0, 59 | PIN_QSPI_IO1, PIN_QSPI_IO2, PIN_QSPI_IO3) {} 60 | 61 | Adafruit_FlashTransport_QSPI::Adafruit_FlashTransport_QSPI( 62 | int8_t sck, int8_t cs, int8_t io0, int8_t io1, int8_t io2, int8_t io3) { 63 | _addr_len = 3; // work with most device if not set 64 | _cmd_read = SFLASH_CMD_QUAD_READ; 65 | _sck = sck; 66 | _cs = cs; 67 | _io0 = io0; 68 | _io1 = io1; 69 | _io2 = io2; 70 | _io3 = io3; 71 | } 72 | 73 | void Adafruit_FlashTransport_QSPI::begin(void) { 74 | // Init QSPI flash 75 | nrfx_qspi_config_t qspi_cfg = { 76 | .xip_offset = 0, 77 | .pins = 78 | { 79 | .sck_pin = (uint8_t)g_ADigitalPinMap[_sck], 80 | .csn_pin = (uint8_t)g_ADigitalPinMap[_cs], 81 | .io0_pin = (uint8_t)g_ADigitalPinMap[_io0], 82 | .io1_pin = (uint8_t)g_ADigitalPinMap[_io1], 83 | .io2_pin = (uint8_t)g_ADigitalPinMap[_io2], 84 | .io3_pin = (uint8_t)g_ADigitalPinMap[_io3], 85 | }, 86 | .prot_if = {.readoc = NRF_QSPI_READOC_READ4O, // 0x6B read command 87 | .writeoc = NRF_QSPI_WRITEOC_PP4O, // 0x32 write command 88 | .addrmode = NRF_QSPI_ADDRMODE_24BIT, 89 | .dpmconfig = false}, 90 | .phy_if = 91 | { 92 | .sck_delay = 10, 93 | .dpmen = false, 94 | .spi_mode = NRF_QSPI_MODE_0, 95 | .sck_freq = NRF_QSPI_FREQ_32MDIV16, // start with low 2 Mhz speed 96 | }, 97 | .irq_priority = 7}; 98 | 99 | // No callback for blocking API 100 | nrfx_qspi_init(&qspi_cfg, NULL, NULL); 101 | } 102 | 103 | void Adafruit_FlashTransport_QSPI::end(void) { nrfx_qspi_uninit(); } 104 | 105 | void Adafruit_FlashTransport_QSPI::setClockSpeed(uint32_t clock_hz, 106 | uint32_t read_hz) { 107 | (void)read_hz; 108 | // Start at 16 MHz and go down. 109 | // At 32 MHz nRF52840 doesn't work reliably !!! 110 | // clkdiv = 0 is 32 Mhz 111 | // clkdiv = 1 is 16 MHz, etc. 112 | uint8_t clkdiv = 1; 113 | while ((32000000UL / (clkdiv + 1) > clock_hz) && (clkdiv < 16)) { 114 | clkdiv++; 115 | } 116 | 117 | // delay is set to one freq period 118 | uint8_t delay = 1; 119 | 120 | if (clkdiv) { 121 | delay = (1UL << (clkdiv - 1)); 122 | } 123 | 124 | NRF_QSPI->IFCONFIG1 &= 125 | ~(QSPI_IFCONFIG1_SCKFREQ_Msk | QSPI_IFCONFIG1_SCKDELAY_Msk); 126 | NRF_QSPI->IFCONFIG1 |= (clkdiv << QSPI_IFCONFIG1_SCKFREQ_Pos) | 127 | (delay << QSPI_IFCONFIG1_SCKDELAY_Pos); 128 | } 129 | 130 | bool Adafruit_FlashTransport_QSPI::runCommand(uint8_t command) { 131 | nrf_qspi_cinstr_conf_t cinstr_cfg = {.opcode = command, 132 | .length = NRF_QSPI_CINSTR_LEN_1B, 133 | .io2_level = true, 134 | .io3_level = true, 135 | .wipwait = false, 136 | .wren = false}; 137 | 138 | return nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL) == NRFX_SUCCESS; 139 | } 140 | 141 | bool Adafruit_FlashTransport_QSPI::readCommand(uint8_t command, 142 | uint8_t *response, 143 | uint32_t len) { 144 | nrf_qspi_cinstr_conf_t cinstr_cfg = {.opcode = command, 145 | .length = 146 | (nrf_qspi_cinstr_len_t)(len + 1), 147 | .io2_level = true, 148 | .io3_level = true, 149 | .wipwait = false, 150 | .wren = false}; 151 | return nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, response) == NRFX_SUCCESS; 152 | } 153 | 154 | bool Adafruit_FlashTransport_QSPI::writeCommand(uint8_t command, 155 | uint8_t const *data, 156 | uint32_t len) { 157 | nrf_qspi_cinstr_conf_t cinstr_cfg = { 158 | .opcode = command, 159 | .length = (nrf_qspi_cinstr_len_t)(len + 1), 160 | .io2_level = true, 161 | .io3_level = true, 162 | .wipwait = false, 163 | .wren = false // We do this manually. 164 | }; 165 | return nrfx_qspi_cinstr_xfer(&cinstr_cfg, data, NULL) == NRFX_SUCCESS; 166 | } 167 | 168 | bool Adafruit_FlashTransport_QSPI::eraseCommand(uint8_t command, 169 | uint32_t address) { 170 | nrf_qspi_erase_len_t erase_len; 171 | 172 | if (command == SFLASH_CMD_ERASE_SECTOR) { 173 | erase_len = NRF_QSPI_ERASE_LEN_4KB; 174 | } else if (command == SFLASH_CMD_ERASE_BLOCK) { 175 | erase_len = NRF_QSPI_ERASE_LEN_64KB; 176 | } else { 177 | return false; 178 | } 179 | 180 | return NRFX_SUCCESS == nrfx_qspi_erase(erase_len, address); 181 | } 182 | 183 | //--------------------------------------------------------------------+ 184 | // Read & Write 185 | //--------------------------------------------------------------------+ 186 | static uint32_t read_write_odd(bool read_op, uint32_t addr, uint8_t *data, 187 | uint32_t len) { 188 | uint8_t buf4[4] __attribute__((aligned(4))); 189 | uint32_t count = 4 - (((uint32_t)data) & 0x03); 190 | count = min(count, len); 191 | 192 | if (read_op) { 193 | if (NRFX_SUCCESS != nrfx_qspi_read(buf4, 4, addr)) { 194 | return 0; 195 | } 196 | 197 | memcpy(data, buf4, count); 198 | } else { 199 | memset(buf4, 0xff, 4); 200 | memcpy(buf4, data, count); 201 | 202 | if (NRFX_SUCCESS != nrfx_qspi_write(buf4, 4, addr)) { 203 | return 0; 204 | } 205 | } 206 | 207 | return count; 208 | } 209 | 210 | static bool read_write_memory(bool read_op, uint32_t addr, uint8_t *data, 211 | uint32_t len) { 212 | // buffer is not 4-byte aligned 213 | if (((uint32_t)data) & 3) { 214 | uint32_t const count = read_write_odd(read_op, addr, data, len); 215 | if (!count) { 216 | return false; 217 | } 218 | 219 | data += count; 220 | addr += count; 221 | len -= count; 222 | } 223 | 224 | // nrfx_qspi_read works in 4 byte increments, though it doesn't 225 | // signal an error if sz is not a multiple of 4. Read (directly into data) 226 | // all but the last 1, 2, or 3 bytes depending on the (remaining) length. 227 | if (len > 3) { 228 | uint32_t const len4 = len & ~(uint32_t)3; 229 | 230 | if (read_op) { 231 | if (NRFX_SUCCESS != nrfx_qspi_read(data, len4, addr)) { 232 | return 0; 233 | } 234 | } else { 235 | if (NRFX_SUCCESS != nrfx_qspi_write(data, len4, addr)) { 236 | return 0; 237 | } 238 | } 239 | 240 | data += len4; 241 | addr += len4; 242 | len -= len4; 243 | } 244 | 245 | // Now, if we have any bytes left over, we must do a final read of 4 246 | // bytes and copy 1, 2, or 3 bytes to data. 247 | if (len) { 248 | if (!read_write_odd(read_op, addr, data, len)) { 249 | return false; 250 | } 251 | } 252 | 253 | return true; 254 | } 255 | 256 | bool Adafruit_FlashTransport_QSPI::readMemory(uint32_t addr, uint8_t *data, 257 | uint32_t len) { 258 | return read_write_memory(true, addr, data, len); 259 | } 260 | 261 | bool Adafruit_FlashTransport_QSPI::writeMemory(uint32_t addr, 262 | uint8_t const *data, 263 | uint32_t len) { 264 | return read_write_memory(false, addr, (uint8_t *)data, len); 265 | } 266 | 267 | #endif 268 | -------------------------------------------------------------------------------- /examples/SdFat_full_usage/SdFat_full_usage.ino: -------------------------------------------------------------------------------- 1 | // Adafruit SPI Flash FatFs Full Usage Example 2 | // Author: Tony DiCola 3 | // 4 | // This is an example of all the functions in the SPI Flash 5 | // FatFs library. Note that you MUST have a flash chip that's 6 | // formatted with a flash filesystem before running. See the 7 | // fatfs_format example to perform this formatting. 8 | // 9 | // In general the API for this library closely follows the API 10 | // for the Arduino SD card library. However instead of interacting 11 | // with a global SD object you create an instance of a fatfs class 12 | // and use its open, exists, etc. functions. See the SD library 13 | // reference for more inspiration and examples to adapt: 14 | // https://www.arduino.cc/en/reference/SD 15 | // 16 | // Usage: 17 | // - Modify the pins and type of fatfs object in the config 18 | // section below if necessary (usually not necessary). 19 | // - Upload this sketch to your M0 express board. 20 | // - Open the serial monitor at 115200 baud. You should see the 21 | // example start to run and messages printed to the monitor. 22 | // If you don't see anything close the serial monitor, press 23 | // the board reset button, wait a few seconds, then open the 24 | // serial monitor again. 25 | #include "SdFat_Adafruit_Fork.h" 26 | #include 27 | 28 | #include 29 | 30 | // for flashTransport definition 31 | #include "flash_config.h" 32 | 33 | Adafruit_SPIFlash flash(&flashTransport); 34 | 35 | // file system object from SdFat 36 | FatVolume fatfs; 37 | 38 | #define D_TEST "/test" 39 | #define D_TEST_FOO_BAR "/test/foo/bar" 40 | #define D_TEST_FOO_BAZ "/test/foo/baz" 41 | 42 | #define F_TEST_TEST_TXT "/test/test.txt" 43 | #define F_TEST_FOO_TEST2_TXT "/test/foo/test2.txt" 44 | 45 | void setup() { 46 | // Initialize serial port and wait for it to open before continuing. 47 | Serial.begin(115200); 48 | while (!Serial) { 49 | delay(100); 50 | } 51 | Serial.println(F("Adafruit SPI Flash FatFs Full Usage Example")); 52 | 53 | // Initialize flash library and check its chip ID. 54 | if (!flash.begin()) { 55 | Serial.println(F("Error, failed to initialize flash chip!")); 56 | while (1) { 57 | yield(); 58 | } 59 | } 60 | Serial.print(F("Flash chip JEDEC ID: 0x")); 61 | Serial.println(flash.getJEDECID(), HEX); 62 | 63 | // First call begin to mount the filesystem. Check that it returns true 64 | // to make sure the filesystem was mounted. 65 | if (!fatfs.begin(&flash)) { 66 | Serial.println(F("Error, failed to mount newly formatted filesystem!")); 67 | Serial.println( 68 | F("Was the flash chip formatted with the SdFat_format example?")); 69 | while (1) { 70 | yield(); 71 | } 72 | } 73 | Serial.println(F("Mounted filesystem!")); 74 | 75 | // Check if a directory called 'test' exists and create it if not there. 76 | // Note you should _not_ add a trailing slash (like '/test/') to directory 77 | // names! You can use the same exists function to check for the existence of a 78 | // file too. 79 | if (!fatfs.exists(D_TEST)) { 80 | Serial.println(F("Test directory not found, creating...")); 81 | 82 | // Use mkdir to create directory (note you should _not_ have a trailing 83 | // slash). 84 | fatfs.mkdir(D_TEST); 85 | 86 | if (!fatfs.exists(D_TEST)) { 87 | Serial.println(F("Error, failed to create directory!")); 88 | while (1) { 89 | yield(); 90 | } 91 | } else { 92 | Serial.println(F("Created directory!")); 93 | } 94 | } 95 | 96 | // You can also create all the parent subdirectories automatically with mkdir. 97 | // For example to create the hierarchy /test/foo/bar: 98 | Serial.println(F("Creating deep folder structure...")); 99 | if (!fatfs.exists(D_TEST_FOO_BAR)) { 100 | Serial.println(F("Creating " D_TEST_FOO_BAR)); 101 | fatfs.mkdir(D_TEST_FOO_BAR); 102 | 103 | if (!fatfs.exists(D_TEST_FOO_BAR)) { 104 | Serial.println(F("Error, failed to create directory!")); 105 | while (1) { 106 | yield(); 107 | } 108 | } else { 109 | Serial.println(F("Created directory!")); 110 | } 111 | } 112 | 113 | // This will create the hierarchy /test/foo/baz, even when /test/foo already 114 | // exists: 115 | if (!fatfs.exists(D_TEST_FOO_BAZ)) { 116 | Serial.println(F("Creating " D_TEST_FOO_BAZ)); 117 | fatfs.mkdir(D_TEST_FOO_BAZ); 118 | 119 | if (!fatfs.exists(D_TEST_FOO_BAZ)) { 120 | Serial.println(F("Error, failed to create directory!")); 121 | while (1) { 122 | yield(); 123 | } 124 | } else { 125 | Serial.println(F("Created directory!")); 126 | } 127 | } 128 | 129 | // Create a file in the test directory and write data to it. 130 | // Note the FILE_WRITE parameter which tells the library you intend to 131 | // write to the file. This will create the file if it doesn't exist, 132 | // otherwise it will open the file and start appending new data to the 133 | // end of it. 134 | File32 writeFile = fatfs.open(F_TEST_TEST_TXT, FILE_WRITE); 135 | if (!writeFile) { 136 | Serial.println(F("Error, failed to open " F_TEST_TEST_TXT " for writing!")); 137 | while (1) { 138 | yield(); 139 | } 140 | } 141 | Serial.println(F("Opened file " F_TEST_TEST_TXT " for writing/appending...")); 142 | 143 | // Once open for writing you can print to the file as if you're printing 144 | // to the serial terminal, the same functions are available. 145 | writeFile.println("Hello world!"); 146 | writeFile.print("Hello number: "); 147 | writeFile.println(123, DEC); 148 | writeFile.print("Hello hex number: 0x"); 149 | writeFile.println(123, HEX); 150 | 151 | // Close the file when finished writing. 152 | writeFile.close(); 153 | Serial.println(F("Wrote to file " F_TEST_TEST_TXT "!")); 154 | 155 | // Now open the same file but for reading. 156 | File32 readFile = fatfs.open(F_TEST_TEST_TXT, FILE_READ); 157 | if (!readFile) { 158 | Serial.println(F("Error, failed to open " F_TEST_TEST_TXT " for reading!")); 159 | while (1) { 160 | yield(); 161 | } 162 | } 163 | 164 | // Read data using the same read, find, readString, etc. functions as when 165 | // using the serial class. See SD library File class for more documentation: 166 | // https://www.arduino.cc/en/reference/SD 167 | // Read a line of data: 168 | String line = readFile.readStringUntil('\n'); 169 | Serial.print(F("First line of test.txt: ")); 170 | Serial.println(line); 171 | 172 | // You can get the current position, remaining data, and total size of the 173 | // file: 174 | Serial.print(F("Total size of test.txt (bytes): ")); 175 | Serial.println(readFile.size(), DEC); 176 | Serial.print(F("Current position in test.txt: ")); 177 | Serial.println(readFile.position(), DEC); 178 | Serial.print(F("Available data to read in test.txt: ")); 179 | Serial.println(readFile.available(), DEC); 180 | 181 | // And a few other interesting attributes of a file: 182 | char readName[64]; 183 | readFile.getName(readName, sizeof(readName)); 184 | Serial.print(F("File name: ")); 185 | Serial.println(readName); 186 | Serial.print(F("Is file a directory? ")); 187 | Serial.println(readFile.isDirectory() ? F("Yes") : F("No")); 188 | 189 | // You can seek around inside the file relative to the start of the file. 190 | // For example to skip back to the start (position 0): 191 | if (!readFile.seek(0)) { 192 | Serial.println(F("Error, failed to seek back to start of file!")); 193 | while (1) { 194 | yield(); 195 | } 196 | } 197 | 198 | // And finally to read all the data and print it out a character at a time 199 | // (stopping when end of file is reached): 200 | Serial.println(F("Entire contents of test.txt:")); 201 | while (readFile.available()) { 202 | char c = readFile.read(); 203 | Serial.print(c); 204 | } 205 | 206 | // Close the file when finished reading. 207 | readFile.close(); 208 | 209 | // You can open a directory to list all the children (files and directories). 210 | // Just like the SD library the File type represents either a file or 211 | // directory. 212 | File32 testDir = fatfs.open(D_TEST); 213 | if (!testDir) { 214 | Serial.println(F("Error, failed to open test directory!")); 215 | while (1) { 216 | yield(); 217 | } 218 | } 219 | if (!testDir.isDirectory()) { 220 | Serial.println(F("Error, expected test to be a directory!")); 221 | while (1) { 222 | yield(); 223 | } 224 | } 225 | Serial.println(F("Listing children of directory " D_TEST ":")); 226 | File32 child = testDir.openNextFile(); 227 | while (child) { 228 | char filename[64]; 229 | child.getName(filename, sizeof(filename)); 230 | 231 | // Print the file name and mention if it's a directory. 232 | Serial.print(F("- ")); 233 | Serial.print(filename); 234 | if (child.isDirectory()) { 235 | Serial.print(F(" (directory)")); 236 | } 237 | Serial.println(); 238 | // Keep calling openNextFile to get a new file. 239 | // When you're done enumerating files an unopened one will 240 | // be returned (i.e. testing it for true/false like at the 241 | // top of this while loop will fail). 242 | child = testDir.openNextFile(); 243 | } 244 | 245 | // If you want to list the files in the directory again call 246 | // rewindDirectory(). Then openNextFile will start from the 247 | // top again. 248 | testDir.rewindDirectory(); 249 | 250 | // Delete a file with the remove command. For example create a test2.txt file 251 | // inside /test/foo and then delete it. 252 | File32 test2File = fatfs.open(F_TEST_FOO_TEST2_TXT, FILE_WRITE); 253 | test2File.close(); 254 | Serial.println(F("Deleting " F_TEST_FOO_TEST2_TXT "...")); 255 | if (!fatfs.remove(F_TEST_FOO_TEST2_TXT)) { 256 | Serial.println(F("Error, couldn't delete " F_TEST_FOO_TEST2_TXT " file!")); 257 | while (1) { 258 | yield(); 259 | } 260 | } 261 | Serial.println(F("Deleted file!")); 262 | 263 | // Delete a directory with the rmdir command. Be careful as 264 | // this will delete EVERYTHING in the directory at all levels! 265 | // I.e. this is like running a recursive delete, rm -rf *, in 266 | // unix filesystems! 267 | Serial.println(F("Deleting /test directory and everything inside it...")); 268 | if (!testDir.rmRfStar()) { 269 | Serial.println(F("Error, couldn't delete test directory!")); 270 | while (1) { 271 | yield(); 272 | } 273 | } 274 | // Check that test is really deleted. 275 | if (fatfs.exists(D_TEST)) { 276 | Serial.println(F("Error, test directory was not deleted!")); 277 | while (1) { 278 | yield(); 279 | } 280 | } 281 | Serial.println(F("Test directory was deleted!")); 282 | 283 | Serial.println(F("Finished!")); 284 | } 285 | 286 | void loop() { 287 | // Nothing to be done in the main loop. 288 | delay(100); 289 | } 290 | -------------------------------------------------------------------------------- /examples/SdFat_format/ffconf.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------/ 2 | / FatFs Functional Configurations 3 | /---------------------------------------------------------------------------*/ 4 | 5 | #define FFCONF_DEF 86604 /* Revision ID */ 6 | 7 | /*---------------------------------------------------------------------------/ 8 | / Function Configurations 9 | /---------------------------------------------------------------------------*/ 10 | 11 | #define FF_FS_READONLY 0 12 | /* This option switches read-only configuration. (0:Read/Write or 1:Read-only) 13 | / Read-only configuration removes writing API functions, f_write(), f_sync(), 14 | / f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() 15 | / and optional writing functions as well. */ 16 | 17 | 18 | #define FF_FS_MINIMIZE 3 19 | /* This option defines minimization level to remove some basic API functions. 20 | / 21 | / 0: Basic functions are fully enabled. 22 | / 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() 23 | / are removed. 24 | / 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. 25 | / 3: f_lseek() function is removed in addition to 2. */ 26 | 27 | 28 | #define FF_USE_STRFUNC 0 29 | /* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf(). 30 | / 31 | / 0: Disable string functions. 32 | / 1: Enable without LF-CRLF conversion. 33 | / 2: Enable with LF-CRLF conversion. */ 34 | 35 | 36 | #define FF_USE_FIND 0 37 | /* This option switches filtered directory read functions, f_findfirst() and 38 | / f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ 39 | 40 | 41 | #define FF_USE_MKFS 1 42 | /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ 43 | 44 | 45 | #define FF_USE_FASTSEEK 0 46 | /* This option switches fast seek function. (0:Disable or 1:Enable) */ 47 | 48 | 49 | #define FF_USE_EXPAND 0 50 | /* This option switches f_expand function. (0:Disable or 1:Enable) */ 51 | 52 | 53 | #define FF_USE_CHMOD 0 54 | /* This option switches attribute manipulation functions, f_chmod() and f_utime(). 55 | / (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ 56 | 57 | 58 | #define FF_USE_LABEL 1 59 | /* This option switches volume label functions, f_getlabel() and f_setlabel(). 60 | / (0:Disable or 1:Enable) */ 61 | 62 | 63 | #define FF_USE_FORWARD 0 64 | /* This option switches f_forward() function. (0:Disable or 1:Enable) */ 65 | 66 | 67 | /*---------------------------------------------------------------------------/ 68 | / Locale and Namespace Configurations 69 | /---------------------------------------------------------------------------*/ 70 | 71 | #define FF_CODE_PAGE 437 72 | /* This option specifies the OEM code page to be used on the target system. 73 | / Incorrect code page setting can cause a file open failure. 74 | / 75 | / 437 - U.S. 76 | / 720 - Arabic 77 | / 737 - Greek 78 | / 771 - KBL 79 | / 775 - Baltic 80 | / 850 - Latin 1 81 | / 852 - Latin 2 82 | / 855 - Cyrillic 83 | / 857 - Turkish 84 | / 860 - Portuguese 85 | / 861 - Icelandic 86 | / 862 - Hebrew 87 | / 863 - Canadian French 88 | / 864 - Arabic 89 | / 865 - Nordic 90 | / 866 - Russian 91 | / 869 - Greek 2 92 | / 932 - Japanese (DBCS) 93 | / 936 - Simplified Chinese (DBCS) 94 | / 949 - Korean (DBCS) 95 | / 950 - Traditional Chinese (DBCS) 96 | / 0 - Include all code pages above and configured by f_setcp() 97 | */ 98 | 99 | 100 | #define FF_USE_LFN 0 101 | #define FF_MAX_LFN 255 102 | /* The FF_USE_LFN switches the support for LFN (long file name). 103 | / 104 | / 0: Disable LFN. FF_MAX_LFN has no effect. 105 | / 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. 106 | / 2: Enable LFN with dynamic working buffer on the STACK. 107 | / 3: Enable LFN with dynamic working buffer on the HEAP. 108 | / 109 | / To enable the LFN, ffunicode.c needs to be added to the project. The LFN function 110 | / requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and 111 | / additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled. 112 | / The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can 113 | / be in range of 12 to 255. It is recommended to be set 255 to fully support LFN 114 | / specification. 115 | / When use stack for the working buffer, take care on stack overflow. When use heap 116 | / memory for the working buffer, memory management functions, ff_memalloc() and 117 | / ff_memfree() in ffsystem.c, need to be added to the project. */ 118 | 119 | 120 | #define FF_LFN_UNICODE 0 121 | /* This option switches the character encoding on the API when LFN is enabled. 122 | / 123 | / 0: ANSI/OEM in current CP (TCHAR = char) 124 | / 1: Unicode in UTF-16 (TCHAR = WCHAR) 125 | / 2: Unicode in UTF-8 (TCHAR = char) 126 | / 3: Unicode in UTF-32 (TCHAR = DWORD) 127 | / 128 | / Also behavior of string I/O functions will be affected by this option. 129 | / When LFN is not enabled, this option has no effect. */ 130 | 131 | 132 | #define FF_LFN_BUF 255 133 | #define FF_SFN_BUF 12 134 | /* This set of options defines size of file name members in the FILINFO structure 135 | / which is used to read out directory items. These values should be sufficient for 136 | / the file names to read. The maximum possible length of the read file name depends 137 | / on character encoding. When LFN is not enabled, these options have no effect. */ 138 | 139 | 140 | #define FF_STRF_ENCODE 3 141 | /* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(), 142 | / f_putc(), f_puts and f_printf() convert the character encoding in it. 143 | / This option selects assumption of character encoding ON THE FILE to be 144 | / read/written via those functions. 145 | / 146 | / 0: ANSI/OEM in current CP 147 | / 1: Unicode in UTF-16LE 148 | / 2: Unicode in UTF-16BE 149 | / 3: Unicode in UTF-8 150 | */ 151 | 152 | 153 | #define FF_FS_RPATH 0 154 | /* This option configures support for relative path. 155 | / 156 | / 0: Disable relative path and remove related functions. 157 | / 1: Enable relative path. f_chdir() and f_chdrive() are available. 158 | / 2: f_getcwd() function is available in addition to 1. 159 | */ 160 | 161 | 162 | /*---------------------------------------------------------------------------/ 163 | / Drive/Volume Configurations 164 | /---------------------------------------------------------------------------*/ 165 | 166 | #define FF_VOLUMES 1 167 | /* Number of volumes (logical drives) to be used. (1-10) */ 168 | 169 | 170 | #define FF_STR_VOLUME_ID 0 171 | #define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" 172 | /* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. 173 | / When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive 174 | / number in the path name. FF_VOLUME_STRS defines the volume ID strings for each 175 | / logical drives. Number of items must not be less than FF_VOLUMES. Valid 176 | / characters for the volume ID strings are A-Z, a-z and 0-9, however, they are 177 | / compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is 178 | / not defined, a user defined volume string table needs to be defined as: 179 | / 180 | / const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... 181 | */ 182 | 183 | 184 | #define FF_MULTI_PARTITION 0 185 | /* This option switches support for multiple volumes on the physical drive. 186 | / By default (0), each logical drive number is bound to the same physical drive 187 | / number and only an FAT volume found on the physical drive will be mounted. 188 | / When this function is enabled (1), each logical drive number can be bound to 189 | / arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() 190 | / function will be available. */ 191 | 192 | 193 | #define FF_MIN_SS 512 194 | #define FF_MAX_SS 512 195 | /* This set of options configures the range of sector size to be supported. (512, 196 | / 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and 197 | / harddisk. But a larger value may be required for on-board flash memory and some 198 | / type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured 199 | / for variable sector size mode and disk_ioctl() function needs to implement 200 | / GET_SECTOR_SIZE command. */ 201 | 202 | 203 | #define FF_USE_TRIM 0 204 | /* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) 205 | / To enable Trim function, also CTRL_TRIM command should be implemented to the 206 | / disk_ioctl() function. */ 207 | 208 | 209 | #define FF_FS_NOFSINFO 0 210 | /* If you need to know correct free space on the FAT32 volume, set bit 0 of this 211 | / option, and f_getfree() function at first time after volume mount will force 212 | / a full FAT scan. Bit 1 controls the use of last allocated cluster number. 213 | / 214 | / bit0=0: Use free cluster count in the FSINFO if available. 215 | / bit0=1: Do not trust free cluster count in the FSINFO. 216 | / bit1=0: Use last allocated cluster number in the FSINFO if available. 217 | / bit1=1: Do not trust last allocated cluster number in the FSINFO. 218 | */ 219 | 220 | 221 | 222 | /*---------------------------------------------------------------------------/ 223 | / System Configurations 224 | /---------------------------------------------------------------------------*/ 225 | 226 | #define FF_FS_TINY 0 227 | /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) 228 | / At the tiny configuration, size of file object (FIL) is shrunk FF_MAX_SS bytes. 229 | / Instead of private sector buffer eliminated from the file object, common sector 230 | / buffer in the filesystem object (FATFS) is used for the file data transfer. */ 231 | 232 | 233 | #define FF_FS_EXFAT 0 234 | /* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) 235 | / To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1) 236 | / Note that enabling exFAT discards ANSI C (C89) compatibility. */ 237 | 238 | 239 | #define FF_FS_NORTC 1 240 | #define FF_NORTC_MON 1 241 | #define FF_NORTC_MDAY 1 242 | #define FF_NORTC_YEAR 2019 243 | /* The option FF_FS_NORTC switches timestamp function. If the system does not have 244 | / any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable 245 | / the timestamp function. Every object modified by FatFs will have a fixed timestamp 246 | / defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. 247 | / To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be 248 | / added to the project to read current time form real-time clock. FF_NORTC_MON, 249 | / FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. 250 | / These options have no effect at read-only configuration (FF_FS_READONLY = 1). */ 251 | 252 | 253 | #define FF_FS_LOCK 0 254 | /* The option FF_FS_LOCK switches file lock function to control duplicated file open 255 | / and illegal operation to open objects. This option must be 0 when FF_FS_READONLY 256 | / is 1. 257 | / 258 | / 0: Disable file lock function. To avoid volume corruption, application program 259 | / should avoid illegal open, remove and rename to the open objects. 260 | / >0: Enable file lock function. The value defines how many files/sub-directories 261 | / can be opened simultaneously under file lock control. Note that the file 262 | / lock control is independent of re-entrancy. */ 263 | 264 | 265 | /* #include // O/S definitions */ 266 | #define FF_FS_REENTRANT 0 267 | #define FF_FS_TIMEOUT 1000 268 | #define FF_SYNC_t HANDLE 269 | /* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs 270 | / module itself. Note that regardless of this option, file access to different 271 | / volume is always re-entrant and volume control functions, f_mount(), f_mkfs() 272 | / and f_fdisk() function, are always not re-entrant. Only file/directory access 273 | / to the same volume is under control of this function. 274 | / 275 | / 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. 276 | / 1: Enable re-entrancy. Also user provided synchronization handlers, 277 | / ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() 278 | / function, must be added to the project. Samples are available in 279 | / option/syscall.c. 280 | / 281 | / The FF_FS_TIMEOUT defines timeout period in unit of time tick. 282 | / The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, 283 | / SemaphoreHandle_t and etc. A header file for O/S definitions needs to be 284 | / included somewhere in the scope of ff.h. */ 285 | 286 | 287 | 288 | /*--- End of configuration options ---*/ 289 | --------------------------------------------------------------------------------