diff --git a/libraries/SerialFlash/SerialFlash.h b/libraries/SerialFlash/SerialFlash.h deleted file mode 100644 index e56df624..00000000 --- a/libraries/SerialFlash/SerialFlash.h +++ /dev/null @@ -1,132 +0,0 @@ -/* SerialFlash Library - for filesystem-like access to SPI Serial Flash memory - * https://github.com/PaulStoffregen/SerialFlash - * Copyright (C) 2015, Paul Stoffregen, paul@pjrc.com - * - * Development of this library was funded by PJRC.COM, LLC by sales of Teensy. - * Please support PJRC's efforts to develop open source software by purchasing - * Teensy or other genuine PJRC products. - * - * 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: - * - * The above copyright notice, development funding notice, and this permission - * notice shall be included in all copies or substantial portions of the Software. - * - * 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. - */ - -#ifndef SerialFlash_h_ -#define SerialFlash_h_ - -#include -#include - -class SerialFlashFile; - -class SerialFlashChip -{ -public: - static bool begin(uint8_t pin = 6); - static uint32_t capacity(const uint8_t *id); - static uint32_t blockSize(); - static void sleep(); - static void wakeup(); - static void readID(uint8_t *buf); - static void readSerialNumber(uint8_t *buf); - static void read(uint32_t addr, void *buf, uint32_t len); - static bool ready(); - static void wait(); - static void write(uint32_t addr, const void *buf, uint32_t len); - static void eraseAll(); - static void eraseBlock(uint32_t addr); - - static SerialFlashFile open(const char *filename); - static bool create(const char *filename, uint32_t length, uint32_t align = 0); - static bool createErasable(const char *filename, uint32_t length) { - return create(filename, length, blockSize()); - } - static bool exists(const char *filename); - static bool remove(const char *filename); - static bool remove(SerialFlashFile &file); - static void opendir() { dirindex = 0; } - static bool readdir(char *filename, uint32_t strsize, uint32_t &filesize); -private: - static uint16_t dirindex; // current position for readdir() - static uint8_t flags; // chip features - static uint8_t busy; // 0 = ready - // 1 = suspendable program operation - // 2 = suspendable erase operation - // 3 = busy for realz!! -}; - -extern SerialFlashChip SerialFlash; - - -class SerialFlashFile -{ -public: - SerialFlashFile() : address(0) { - } - operator bool() { - if (address > 0) return true; - return false; - } - uint32_t read(void *buf, uint32_t rdlen) { - if (offset + rdlen > length) { - if (offset >= length) return 0; - rdlen = length - offset; - } - SerialFlash.read(address + offset, buf, rdlen); - offset += rdlen; - return rdlen; - } - uint32_t write(const void *buf, uint32_t wrlen) { - if (offset + wrlen > length) { - if (offset >= length) return 0; - wrlen = length - offset; - } - SerialFlash.write(address + offset, buf, wrlen); - offset += wrlen; - return wrlen; - } - void seek(uint32_t n) { - offset = n; - } - uint32_t position() { - return offset; - } - uint32_t size() { - return length; - } - uint32_t available() { - if (offset >= length) return 0; - return length - offset; - } - void erase(); - void flush() { - } - void close() { - } - uint32_t getFlashAddress() { - return address; - } -protected: - friend class SerialFlashChip; - uint32_t address; // where this file's data begins in the Flash, or zero - uint32_t length; // total length of the data in the Flash chip - uint32_t offset; // current read/write offset in the file - uint16_t dirindex; -}; - - -#endif diff --git a/libraries/SerialFlash/SerialFlashChip.cpp b/libraries/SerialFlash/SerialFlashChip.cpp deleted file mode 100644 index 4e467f57..00000000 --- a/libraries/SerialFlash/SerialFlashChip.cpp +++ /dev/null @@ -1,523 +0,0 @@ -/* SerialFlash Library - for filesystem-like access to SPI Serial Flash memory - * https://github.com/PaulStoffregen/SerialFlash - * Copyright (C) 2015, Paul Stoffregen, paul@pjrc.com - * - * Development of this library was funded by PJRC.COM, LLC by sales of Teensy. - * Please support PJRC's efforts to develop open source software by purchasing - * Teensy or other genuine PJRC products. - * - * 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: - * - * The above copyright notice, development funding notice, and this permission - * notice shall be included in all copies or substantial portions of the Software. - * - * 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. - */ - -#include "SerialFlash.h" -#include "util/SerialFlash_directwrite.h" - -#define CSASSERT() DIRECT_WRITE_LOW(cspin_basereg, cspin_bitmask) -#define CSRELEASE() DIRECT_WRITE_HIGH(cspin_basereg, cspin_bitmask) -#define SPICONFIG SPISettings(50000000, MSBFIRST, SPI_MODE0) - -#if defined(__arc__) -// Use SPI1 on Arduino 101 (accesses chip already on the board) -#define SPIPORT SPI1 -#elif 0 -// Add cases here, if you wish to use other SPI ports... -#else -// Otherwise, use the normal SPI port. -#define SPIPORT SPI -#endif - -uint16_t SerialFlashChip::dirindex = 0; -uint8_t SerialFlashChip::flags = 0; -uint8_t SerialFlashChip::busy = 0; - -static volatile IO_REG_TYPE *cspin_basereg; -static IO_REG_TYPE cspin_bitmask; - -#define FLAG_32BIT_ADDR 0x01 // larger than 16 MByte address -#define FLAG_STATUS_CMD70 0x02 // requires special busy flag check -#define FLAG_DIFF_SUSPEND 0x04 // uses 2 different suspend commands -#define FLAG_MULTI_DIE 0x08 // multiple die, don't read cross 32M barrier -#define FLAG_256K_BLOCKS 0x10 // has 256K erase blocks -#define FLAG_DIE_MASK 0xC0 // top 2 bits count during multi-die erase - -void SerialFlashChip::wait(void) -{ - uint32_t status; - //Serial.print("wait-"); - while (1) { - SPIPORT.beginTransaction(SPICONFIG); - CSASSERT(); - if (flags & FLAG_STATUS_CMD70) { - // some Micron chips require this different - // command to detect program and erase completion - SPIPORT.transfer(0x70); - status = SPIPORT.transfer(0); - CSRELEASE(); - SPIPORT.endTransaction(); - //Serial.printf("b=%02x.", status & 0xFF); - if ((status & 0x80)) break; - } else { - // all others work by simply reading the status reg - SPIPORT.transfer(0x05); - status = SPIPORT.transfer(0); - CSRELEASE(); - SPIPORT.endTransaction(); - //Serial.printf("b=%02x.", status & 0xFF); - if (!(status & 1)) break; - } - } - busy = 0; - //Serial.println(); -} - -void SerialFlashChip::read(uint32_t addr, void *buf, uint32_t len) -{ - uint8_t *p = (uint8_t *)buf; - uint8_t b, f, status, cmd; - - memset(p, 0, len); - f = flags; - SPIPORT.beginTransaction(SPICONFIG); - b = busy; - if (b) { - // read status register ... chip may no longer be busy - CSASSERT(); - if (flags & FLAG_STATUS_CMD70) { - SPIPORT.transfer(0x70); - status = SPIPORT.transfer(0); - if ((status & 0x80)) b = 0; - } else { - SPIPORT.transfer(0x05); - status = SPIPORT.transfer(0); - if (!(status & 1)) b = 0; - } - CSRELEASE(); - if (b == 0) { - // chip is no longer busy :-) - busy = 0; - } else if (b < 3) { - // TODO: this may not work on Spansion chips - // which apparently have 2 different suspend - // commands, for program vs erase - CSASSERT(); - SPIPORT.transfer(0x06); // write enable (Micron req'd) - CSRELEASE(); - delayMicroseconds(1); - cmd = 0x75; //Suspend program/erase for almost all chips - // but Spansion just has to be different for program suspend! - if ((f & FLAG_DIFF_SUSPEND) && (b == 1)) cmd = 0x85; - CSASSERT(); - SPIPORT.transfer(cmd); // Suspend command - CSRELEASE(); - if (f & FLAG_STATUS_CMD70) { - // Micron chips don't actually suspend until flags read - CSASSERT(); - SPIPORT.transfer(0x70); - do { - status = SPIPORT.transfer(0); - } while (!(status & 0x80)); - CSRELEASE(); - } else { - CSASSERT(); - SPIPORT.transfer(0x05); - do { - status = SPIPORT.transfer(0); - } while ((status & 0x01)); - CSRELEASE(); - } - } else { - // chip is busy with an operation that can not suspend - SPIPORT.endTransaction(); // is this a good idea? - wait(); // should we wait without ending - b = 0; // the transaction?? - SPIPORT.beginTransaction(SPICONFIG); - } - } - do { - uint32_t rdlen = len; - if (f & FLAG_MULTI_DIE) { - if ((addr & 0xFE000000) != ((addr + len - 1) & 0xFE000000)) { - rdlen = 0x2000000 - (addr & 0x1FFFFFF); - } - } - CSASSERT(); - // TODO: FIFO optimize.... - if (f & FLAG_32BIT_ADDR) { - SPIPORT.transfer(0x03); - SPIPORT.transfer16(addr >> 16); - SPIPORT.transfer16(addr); - } else { - SPIPORT.transfer16(0x0300 | ((addr >> 16) & 255)); - SPIPORT.transfer16(addr); - } - SPIPORT.transfer(p, rdlen); - CSRELEASE(); - p += rdlen; - addr += rdlen; - len -= rdlen; - } while (len > 0); - if (b) { - CSASSERT(); - SPIPORT.transfer(0x06); // write enable (Micron req'd) - CSRELEASE(); - delayMicroseconds(1); - cmd = 0x7A; - if ((f & FLAG_DIFF_SUSPEND) && (b == 1)) cmd = 0x8A; - CSASSERT(); - SPIPORT.transfer(cmd); // Resume program/erase - CSRELEASE(); - } - SPIPORT.endTransaction(); -} - -void SerialFlashChip::write(uint32_t addr, const void *buf, uint32_t len) -{ - const uint8_t *p = (const uint8_t *)buf; - uint32_t max, pagelen; - - //Serial.printf("WR: addr %08X, len %d\n", addr, len); - do { - if (busy) wait(); - SPIPORT.beginTransaction(SPICONFIG); - CSASSERT(); - // write enable command - SPIPORT.transfer(0x06); - CSRELEASE(); - max = 256 - (addr & 0xFF); - pagelen = (len <= max) ? len : max; - //Serial.printf("WR: addr %08X, pagelen %d\n", addr, pagelen); - delayMicroseconds(1); // TODO: reduce this, but prefer safety first - CSASSERT(); - if (flags & FLAG_32BIT_ADDR) { - SPIPORT.transfer(0x02); // program page command - SPIPORT.transfer16(addr >> 16); - SPIPORT.transfer16(addr); - } else { - SPIPORT.transfer16(0x0200 | ((addr >> 16) & 255)); - SPIPORT.transfer16(addr); - } - addr += pagelen; - len -= pagelen; - do { - SPIPORT.transfer(*p++); - } while (--pagelen > 0); - CSRELEASE(); - busy = 4; - SPIPORT.endTransaction(); - } while (len > 0); -} - -void SerialFlashChip::eraseAll() -{ - if (busy) wait(); - uint8_t id[5]; - readID(id); - //Serial.printf("ID: %02X %02X %02X\n", id[0], id[1], id[2]); - if (id[0] == 0x20 && id[2] >= 0x20 && id[2] <= 0x22) { - // Micron's multi-die chips require special die erase commands - // N25Q512A 20 BA 20 2 dies 32 Mbyte/die 65 nm transitors - // N25Q00AA 20 BA 21 4 dies 32 Mbyte/die 65 nm transitors - // MT25QL02GC 20 BA 22 2 dies 128 Mbyte/die 45 nm transitors - uint8_t die_count = 2; - if (id[2] == 0x21) die_count = 4; - uint8_t die_index = flags >> 6; - //Serial.printf("Micron die erase %d\n", die_index); - flags &= 0x3F; - if (die_index >= die_count) return; // all dies erased :-) - uint8_t die_size = 2; // in 16 Mbyte units - if (id[2] == 0x22) die_size = 8; - SPIPORT.beginTransaction(SPICONFIG); - CSASSERT(); - SPIPORT.transfer(0x06); // write enable command - CSRELEASE(); - delayMicroseconds(1); - CSASSERT(); - // die erase command - SPIPORT.transfer(0xC4); - SPIPORT.transfer16((die_index * die_size) << 8); - SPIPORT.transfer16(0x0000); - CSRELEASE(); - //Serial.printf("Micron erase begin\n"); - flags |= (die_index + 1) << 6; - } else { - // All other chips support the bulk erase command - SPIPORT.beginTransaction(SPICONFIG); - CSASSERT(); - // write enable command - SPIPORT.transfer(0x06); - CSRELEASE(); - delayMicroseconds(1); - CSASSERT(); - // bulk erase command - SPIPORT.transfer(0xC7); - CSRELEASE(); - SPIPORT.endTransaction(); - } - busy = 3; -} - -void SerialFlashChip::eraseBlock(uint32_t addr) -{ - uint8_t f = flags; - if (busy) wait(); - SPIPORT.beginTransaction(SPICONFIG); - CSASSERT(); - SPIPORT.transfer(0x06); // write enable command - CSRELEASE(); - delayMicroseconds(1); - CSASSERT(); - if (f & FLAG_32BIT_ADDR) { - SPIPORT.transfer(0xD8); - SPIPORT.transfer16(addr >> 16); - SPIPORT.transfer16(addr); - } else { - SPIPORT.transfer16(0xD800 | ((addr >> 16) & 255)); - SPIPORT.transfer16(addr); - } - CSRELEASE(); - SPIPORT.endTransaction(); - busy = 2; -} - - -bool SerialFlashChip::ready() -{ - uint32_t status; - if (!busy) return true; - SPIPORT.beginTransaction(SPICONFIG); - CSASSERT(); - if (flags & FLAG_STATUS_CMD70) { - // some Micron chips require this different - // command to detect program and erase completion - SPIPORT.transfer(0x70); - status = SPIPORT.transfer(0); - CSRELEASE(); - SPIPORT.endTransaction(); - //Serial.printf("ready=%02x\n", status & 0xFF); - if ((status & 0x80) == 0) return false; - } else { - // all others work by simply reading the status reg - SPIPORT.transfer(0x05); - status = SPIPORT.transfer(0); - CSRELEASE(); - SPIPORT.endTransaction(); - //Serial.printf("ready=%02x\n", status & 0xFF); - if ((status & 1)) return false; - } - busy = 0; - if (flags & 0xC0) { - // continue a multi-die erase - eraseAll(); - return false; - } - return true; -} - - -#define ID0_WINBOND 0xEF -#define ID0_SPANSION 0x01 -#define ID0_MICRON 0x20 -#define ID0_MACRONIX 0xC2 -#define ID0_SST 0xBF - -//#define FLAG_32BIT_ADDR 0x01 // larger than 16 MByte address -//#define FLAG_STATUS_CMD70 0x02 // requires special busy flag check -//#define FLAG_DIFF_SUSPEND 0x04 // uses 2 different suspend commands -//#define FLAG_256K_BLOCKS 0x10 // has 256K erase blocks - -bool SerialFlashChip::begin(uint8_t pin) -{ - uint8_t id[5]; - uint8_t f; - uint32_t size; - - cspin_basereg = PIN_TO_BASEREG(pin); - cspin_bitmask = PIN_TO_BITMASK(pin); - SPIPORT.begin(); - pinMode(pin, OUTPUT); - CSRELEASE(); - readID(id); - f = 0; - size = capacity(id); - if (size > 16777216) { - // more than 16 Mbyte requires 32 bit addresses - f |= FLAG_32BIT_ADDR; - SPIPORT.beginTransaction(SPICONFIG); - if (id[0] == ID0_SPANSION) { - // spansion uses MSB of bank register - CSASSERT(); - SPIPORT.transfer16(0x1780); // bank register write - CSRELEASE(); - } else { - // micron & winbond & macronix use command - CSASSERT(); - SPIPORT.transfer(0x06); // write enable - CSRELEASE(); - delayMicroseconds(1); - CSASSERT(); - SPIPORT.transfer(0xB7); // enter 4 byte addr mode - CSRELEASE(); - } - SPIPORT.endTransaction(); - if (id[0] == ID0_MICRON) f |= FLAG_MULTI_DIE; - } - if (id[0] == ID0_SPANSION) { - // Spansion has separate suspend commands - f |= FLAG_DIFF_SUSPEND; - if (!id[4]) { - // Spansion chips with id[4] == 0 use 256K sectors - f |= FLAG_256K_BLOCKS; - } - } - if (id[0] == ID0_MICRON) { - // Micron requires busy checks with a different command - f |= FLAG_STATUS_CMD70; // TODO: all or just multi-die chips? - } - flags = f; - readID(id); - return true; -} - -// chips tested: https://github.com/PaulStoffregen/SerialFlash/pull/12#issuecomment-169596992 -// -void SerialFlashChip::sleep() -{ - if (busy) wait(); - SPIPORT.beginTransaction(SPICONFIG); - CSASSERT(); - SPIPORT.transfer(0xB9); // Deep power down command - CSRELEASE(); -} - -void SerialFlashChip::wakeup() -{ - SPIPORT.beginTransaction(SPICONFIG); - CSASSERT(); - SPIPORT.transfer(0xAB); // Wake up from deep power down command - CSRELEASE(); -} - -void SerialFlashChip::readID(uint8_t *buf) -{ - if (busy) wait(); - SPIPORT.beginTransaction(SPICONFIG); - CSASSERT(); - SPIPORT.transfer(0x9F); - buf[0] = SPIPORT.transfer(0); // manufacturer ID - buf[1] = SPIPORT.transfer(0); // memory type - buf[2] = SPIPORT.transfer(0); // capacity - if (buf[0] == ID0_SPANSION) { - buf[3] = SPIPORT.transfer(0); // ID-CFI - buf[4] = SPIPORT.transfer(0); // sector size - } - CSRELEASE(); - SPIPORT.endTransaction(); - //Serial.printf("ID: %02X %02X %02X\n", buf[0], buf[1], buf[2]); -} - -void SerialFlashChip::readSerialNumber(uint8_t *buf) //needs room for 8 bytes -{ - if (busy) wait(); - SPIPORT.beginTransaction(SPICONFIG); - CSASSERT(); - SPIPORT.transfer(0x4B); - SPIPORT.transfer16(0); - SPIPORT.transfer16(0); - for (int i=0; i<8; i++) { - buf[i] = SPIPORT.transfer(0); - } - CSRELEASE(); - SPIPORT.endTransaction(); -// Serial.printf("Serial Number: %02X %02X %02X %02X %02X %02X %02X %02X\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); -} - -uint32_t SerialFlashChip::capacity(const uint8_t *id) -{ - uint32_t n = 1048576; // unknown chips, default to 1 MByte - - if (id[2] >= 16 && id[2] <= 31) { - n = 1ul << id[2]; - } else - if (id[2] >= 32 && id[2] <= 37) { - n = 1ul << (id[2] - 6); - } else - if ((id[0]==0 && id[1]==0 && id[2]==0) || - (id[0]==255 && id[1]==255 && id[2]==255)) { - n = 0; - } - //Serial.printf("capacity %lu\n", n); - return n; -} - -uint32_t SerialFlashChip::blockSize() -{ - // Spansion chips >= 512 mbit use 256K sectors - if (flags & FLAG_256K_BLOCKS) return 262144; - // everything else seems to have 64K sectors - return 65536; -} - - - - -/* -Chip Uniform Sector Erase - 20/21 52 D8/DC - ----- -- ----- -W25Q64CV 4 32 64 -W25Q128FV 4 32 64 -S25FL127S 64 -N25Q512A 4 64 -N25Q00AA 4 64 -S25FL512S 256 -SST26VF032 4 -*/ - - - -// size sector busy pgm/erase chip -// Part Mbyte kbyte ID bytes cmd suspend erase -// ---- ---- ----- -------- --- ------- ----- -// Winbond W25Q64CV 8 64 EF 40 17 -// Winbond W25Q128FV 16 64 EF 40 18 05 single 60 & C7 -// Winbond W25Q256FV 32 64 EF 40 19 -// Spansion S25FL064A 8 ? 01 02 16 -// Spansion S25FL127S 16 64 01 20 18 05 -// Spansion S25FL128P 16 64 01 20 18 -// Spansion S25FL256S 32 64 01 02 19 05 60 & C7 -// Spansion S25FL512S 64 256 01 02 20 -// Macronix MX25L12805D 16 ? C2 20 18 -// Macronix MX66L51235F 64 C2 20 1A -// Numonyx M25P128 16 ? 20 20 18 -// Micron M25P80 1 ? 20 20 14 -// Micron N25Q128A 16 64 20 BA 18 -// Micron N25Q512A 64 ? 20 BA 20 70 single C4 x2 -// Micron N25Q00AA 128 64 20 BA 21 single C4 x4 -// Micron MT25QL02GC 256 64 20 BA 22 70 C4 x2 -// SST SST25WF010 1/8 ? BF 25 02 -// SST SST25WF020 1/4 ? BF 25 03 -// SST SST25WF040 1/2 ? BF 25 04 -// SST SST25VF016B 1 ? BF 25 41 -// SST26VF016 ? BF 26 01 -// SST26VF032 ? BF 26 02 -// SST25VF032 4 64 BF 25 4A -// SST26VF064 8 ? BF 26 43 -// LE25U40CMC 1/2 64 62 06 13 - -SerialFlashChip SerialFlash; diff --git a/libraries/SerialFlash/SerialFlashDirectory.cpp b/libraries/SerialFlash/SerialFlashDirectory.cpp deleted file mode 100644 index 116c14ec..00000000 --- a/libraries/SerialFlash/SerialFlashDirectory.cpp +++ /dev/null @@ -1,395 +0,0 @@ -/* SerialFlash Library - for filesystem-like access to SPI Serial Flash memory - * https://github.com/PaulStoffregen/SerialFlash - * Copyright (C) 2015, Paul Stoffregen, paul@pjrc.com - * - * Development of this library was funded by PJRC.COM, LLC by sales of Teensy. - * Please support PJRC's efforts to develop open source software by purchasing - * Teensy or other genuine PJRC products. - * - * 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: - * - * The above copyright notice, development funding notice, and this permission - * notice shall be included in all copies or substantial portions of the Software. - * - * 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. - */ - -#include "SerialFlash.h" - -/* On-chip SerialFlash file allocation data structures: - - uint32_t signature = 0xFA96554C; - uint16_t maxfiles - uint16_t stringssize // div by 4 - uint16_t hashes[maxfiles] - struct { - uint32_t file_begin - uint32_t file_length - uint16_t string_index // div4 - } fileinfo[maxfiles] - char strings[stringssize] - -A 32 bit signature is stored at the beginning of the flash memory. -If 0xFFFFFFFF is seen, the entire chip should be assumed blank. -If any value other than 0xFA96554C is found, a different data format -is stored. This could should refuse to access the flash. - -The next 4 bytes store number of files and size of the strings -section, which allow the position of every other item to be found. -The string section size is the 16 bit integer times 4, which allows -up to 262140 bytes for string data. - -An array of 16 bit filename hashes allows for quick linear search -for potentially matching filenames. A hash value of 0xFFFF indicates -no file is allocated for the remainder of the array. - -Following the hashes, and array of 10 byte structs give the location -and length of the file's actual data, and the offset of its filename -in the strings section. - -Strings are null terminated. The remainder of the chip is file data. -*/ - -#define DEFAULT_MAXFILES 600 -#define DEFAULT_STRINGS_SIZE 25560 - - -static uint32_t check_signature(void) -{ - uint32_t sig[2]; - - SerialFlash.read(0, sig, 8); - //Serial.printf("sig: %08X %08X\n", sig[0], sig[1]); - if (sig[0] == 0xFA96554C) return sig[1]; - if (sig[0] == 0xFFFFFFFF) { - sig[0] = 0xFA96554C; - sig[1] = ((uint32_t)(DEFAULT_STRINGS_SIZE/4) << 16) | DEFAULT_MAXFILES; - SerialFlash.write(0, sig, 8); - while (!SerialFlash.ready()) ; // TODO: timeout - SerialFlash.read(0, sig, 8); - if (sig[0] == 0xFA96554C) return sig[1]; - } - return 0; -} - -static uint16_t filename_hash(const char *filename) -{ - // http://isthe.com/chongo/tech/comp/fnv/ - uint32_t hash = 2166136261; - const char *p; - - for (p=filename; *p; p++) { - hash ^= *p; - hash *= 16777619; - } - hash = (hash % (uint32_t)0xFFFE) + 1; // all values except 0000 & FFFF - return hash; -} - -static bool filename_compare(const char *filename, uint32_t straddr) -{ - unsigned int i; - const char *p; - char buf[16]; - - p = filename; - while (1) { - SerialFlash.read(straddr, buf, sizeof(buf)); - straddr += sizeof(buf); - for (i=0; i < sizeof(buf); i++) { - if (*p++ != buf[i]) return false; - if (buf[i] == 0) return true; - } - } -} - -#if 0 -void pbuf(const void *buf, uint32_t len) -{ - const uint8_t *p = (const uint8_t *)buf; - do { - Serial.printf("%02X ", *p++); - } while (--len > 0); - Serial.println(); -} -#endif - -SerialFlashFile SerialFlashChip::open(const char *filename) -{ - uint32_t maxfiles, straddr; - uint16_t hash, hashtable[8]; - uint32_t i, n, index=0; - uint32_t buf[3]; - SerialFlashFile file; - - maxfiles = check_signature(); - //Serial.printf("sig: %08X\n", maxfiles); - if (!maxfiles) return file; - maxfiles &= 0xFFFF; - hash = filename_hash(filename); - //Serial.printf("hash %04X for \"%s\"\n", hash, filename); - while (index < maxfiles) { - n = 8; - if (n > maxfiles - index) n = maxfiles - index; - SerialFlash.read(8 + index * 2, hashtable, n * 2); - //Serial.printf(" read %u: ", 8 + index * 2); - //pbuf(hashtable, n * 2); - for (i=0; i < n; i++) { - if (hashtable[i] == hash) { - //Serial.printf(" hash match at index %u\n", index+i); - buf[2] = 0; - SerialFlash.read(8 + maxfiles * 2 + (index+i) * 10, buf, 10); - - //Serial.printf(" maxf=%d, index=%d, i=%d\n", maxfiles, index, i); - //Serial.printf(" read %u: ", 8 + maxfiles * 2 + (index+i) * 10); - //pbuf(buf, 10); - straddr = 8 + maxfiles * 12 + buf[2] * 4; - //Serial.printf(" straddr = %u\n", straddr); - if (filename_compare(filename, straddr)) { - //Serial.printf(" match!\n"); - //Serial.printf(" addr = %u\n", buf[0]); - //Serial.printf(" len = %u\n", buf[1]); - file.address = buf[0]; - file.length = buf[1]; - file.offset = 0; - file.dirindex = index + i; - return file; - } - } else if (hashtable[i] == 0xFFFF) { - return file; - } - } - index += n; - } - return file; -} - -bool SerialFlashChip::exists(const char *filename) -{ - SerialFlashFile file = open(filename); - return (bool)file; -} - -bool SerialFlashChip::remove(const char *filename) -{ - SerialFlashFile file = open(filename); - return remove(file); -} - -bool SerialFlashChip::remove(SerialFlashFile &file) -{ - // To "remove" a file, we simply zero its hash in the lookup - // table, so it can't be found by open(). The space on the - // flash memory is not freed. - if (!file) return false; - uint16_t hash; - SerialFlash.read(8 + file.dirindex * 2, &hash, 2); - //Serial.printf("remove hash %04X at %d index\n", hash, file.dirindex); - hash ^= 0xFFFF; // write zeros to all ones - SerialFlash.write(8 + file.dirindex * 2, &hash, 2); - while (!SerialFlash.ready()) ; // wait... TODO: timeout - SerialFlash.read(8 + file.dirindex * 2, &hash, 2); - if (hash != 0) { - //Serial.printf("remove failed, hash %04X\n", hash); - return false; - } - file.address = 0; - file.length = 0; - return true; -} - -static uint32_t find_first_unallocated_file_index(uint32_t maxfiles) -{ - uint16_t hashtable[8]; - uint32_t i, n, index=0; - - do { - n = 8; - if (index + n > maxfiles) n = maxfiles - index; - SerialFlash.read(8 + index * 2, hashtable, n * 2); - for (i=0; i < n; i++) { - if (hashtable[i] == 0xFFFF) return index + i; - } - index += n; - } while (index < maxfiles); - return 0xFFFFFFFF; -} - -static uint32_t string_length(uint32_t addr) -{ - char buf[16]; - const char *p; - uint32_t len=0; - - while (1) { - SerialFlash.read(addr, buf, sizeof(buf)); - for (p=buf; p < buf + sizeof(buf); p++) { - len++; - if (*p == 0) return len; - } - addr += sizeof(buf); - } -} - -// uint32_t signature = 0xFA96554C; -// uint16_t maxfiles -// uint16_t stringssize // div by 4 -// uint16_t hashes[maxfiles] -// struct { -// uint32_t file_begin -// uint32_t file_length -// uint16_t string_index // div 4 -// } fileinfo[maxfiles] -// char strings[stringssize] - -bool SerialFlashChip::create(const char *filename, uint32_t length, uint32_t align) -{ - uint32_t maxfiles, stringsize; - uint32_t index, buf[3]; - uint32_t address, straddr, len; - SerialFlashFile file; - - // check if the file already exists - if (exists(filename)) return false; - - // first, get the filesystem parameters - maxfiles = check_signature(); - if (!maxfiles) return false; - stringsize = (maxfiles & 0xFFFF0000) >> 14; - maxfiles &= 0xFFFF; - - // find the first unused slot for this file - index = find_first_unallocated_file_index(maxfiles); - if (index >= maxfiles) return false; - //Serial.printf("index = %u\n", index); - // compute where to store the filename and actual data - straddr = 8 + maxfiles * 12; - if (index == 0) { - address = straddr + stringsize; - } else { - buf[2] = 0; - SerialFlash.read(8 + maxfiles * 2 + (index-1) * 10, buf, 10); - address = buf[0] + buf[1]; - straddr += buf[2] * 4; - straddr += string_length(straddr); - straddr = (straddr + 3) & 0x0003FFFC; - } - //Serial.printf("straddr = %u\n", straddr); - //Serial.printf("address = %u\n", address); - //Serial.printf("length = %u\n", length); - if (align > 0) { - // for files aligned to sectors, adjust addr & len - address += align - 1; - address /= align; - address *= align; - //Serial.printf("align address = %u\n", address); - length += align - 1; - length /= align; - length *= align; - //Serial.printf("align length = %u\n", length); - } else { - // always align every file to a page boundary - // for predictable write latency and to guarantee - // write suspend for reading another file can't - // conflict on the same page (2 files never share - // a write page). - address = (address + 255) & 0xFFFFFF00; - } - //Serial.printf("address = %u\n", address); - // last check, if enough space exists... - len = strlen(filename); - // TODO: check for enough string space for filename - - // 5 bytes, to allow for extra 2 bytes in Spansion device IDs - uint8_t id[5]; - SerialFlash.readID(id); - if (address + length > SerialFlash.capacity(id)) return false; - - SerialFlash.write(straddr, filename, len+1); - buf[0] = address; - buf[1] = length; - buf[2] = (straddr - (8 + maxfiles * 12)) / 4; - SerialFlash.write(8 + maxfiles * 2 + index * 10, buf, 10); - //Serial.printf(" write %u: ", 8 + maxfiles * 2 + index * 10); - //pbuf(buf, 10); - while (!SerialFlash.ready()) ; // TODO: timeout - - buf[0] = filename_hash(filename); - //Serial.printf("hash = %04X\n", buf[0]); - SerialFlash.write(8 + index * 2, buf, 2); - while (!SerialFlash.ready()) ; // TODO: timeout - return true; -} - -bool SerialFlashChip::readdir(char *filename, uint32_t strsize, uint32_t &filesize) -{ - uint32_t maxfiles, index, straddr; - uint32_t i, n; - uint32_t buf[2]; - uint16_t hash; - char str[16], *p=filename; - - filename[0] = 0; - maxfiles = check_signature(); - if (!maxfiles) return false; - maxfiles &= 0xFFFF; - index = dirindex; - while (1) { - if (index >= maxfiles) return false; - //Serial.printf("readdir, index = %u\n", index); - SerialFlash.read(8 + index * 2, &hash, 2); - if (hash != 0) break; - index++; // skip deleted entries - } - dirindex = index + 1; - buf[1] = 0; - SerialFlash.read(8 + 4 + maxfiles * 2 + index * 10, buf, 6); - if (buf[0] == 0xFFFFFFFF) return false; - filesize = buf[0]; - straddr = 8 + maxfiles * 12 + buf[1] * 4; - //Serial.printf(" length = %u\n", buf[0]); - //Serial.printf(" straddr = %u\n", straddr); - - while (strsize) { - n = strsize; - if (n > sizeof(str)) n = sizeof(str); - SerialFlash.read(straddr, str, n); - for (i=0; i < n; i++) { - *p++ = str[i]; - if (str[i] == 0) { - //Serial.printf(" name = %s\n", filename); - return true; - } - } - strsize -= n; - straddr += n; - } - *(p - 1) = 0; - //Serial.printf(" name(overflow) = %s\n", filename); - return true; -} - - -void SerialFlashFile::erase() -{ - uint32_t i, blocksize; - - blocksize = SerialFlash.blockSize(); - if (address & (blocksize - 1)) return; // must begin on a block boundary - if (length & (blocksize - 1)) return; // must be exact number of blocks - for (i=0; i < length; i += blocksize) { - SerialFlash.eraseBlock(address + i); - } -} - diff --git a/libraries/SerialFlash/examples/CopyFromSerial/CopyFromSerial.ino b/libraries/SerialFlash/examples/CopyFromSerial/CopyFromSerial.ino deleted file mode 100644 index 6d1af440..00000000 --- a/libraries/SerialFlash/examples/CopyFromSerial/CopyFromSerial.ino +++ /dev/null @@ -1,267 +0,0 @@ -/* - * This is free and unencumbered software released into the public domain. - * - * Anyone is free to copy, modify, publish, use, compile, sell, or - * distribute this software, either in source code form or as a compiled - * binary, for any purpose, commercial or non-commercial, and by any - * means. - * - * In jurisdictions that recognize copyright laws, the author or authors - * of this software dedicate any and all copyright interest in the - * software to the public domain. We make this dedication for the benefit - * of the public at large and to the detriment of our heirs and - * successors. We intend this dedication to be an overt act of - * relinquishment in perpetuity of all present and future rights to this - * software under copyright law. - * - * 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 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. - * - * For more information, please refer to - * ------------------------------------------------------------------------- - * - * This is example code to 1) format an SPI Flash chip, and 2) copy raw - * audio files (mono channel, 16 bit signed, 44100Hz) to it using the - * SerialFlash library. The audio can then be played back using the - * AudioPlaySerialflashRaw object in the Teensy Audio library. - * - * To convert a .wav file to the proper .RAW format, use sox: - * sox input.wav -r 44100 -b 16 --norm -e signed-integer -t raw OUTPUT.RAW remix 1,2 - * - * Note that the OUTPUT.RAW filename must be all caps and contain only the following - * characters: A-Z, 0-9, comma, period, colon, dash, underscore. (The SerialFlash - * library converts filenames to caps, so to avoid confusion we just enforce it here). - * - * It is a little difficult to see what is happening; aswe are using the Serial port - * to upload files, we can't just throw out debug information. Instead, we use the LED - * (pin 13) to convey state. - * - * While the chip is being formatted, the LED (pin 13) will toggle at 1Hz rate. When - * the formatting is done, it flashes quickly (10Hz) for one second, then stays on - * solid. When nothing has been received for 3 seconds, the upload is assumed to be - * completed, and the light goes off. - * - * Use the 'rawfile-uploader.py' python script (included in the extras folder) to upload - * the files. You can start the script as soon as the Teensy is turned on, and the - * USB serial upload will just buffer and wait until the flash is formatted. - * - * This code was written by Wyatt Olson (originally as part - * of Drum Master http://drummaster.digitalcave.ca and later modified into a - * standalone sample). - * - * Enjoy! - * - * SerialFlash library API: https://github.com/PaulStoffregen/SerialFlash - */ - -#include -#include - -//Buffer sizes -#define USB_BUFFER_SIZE 128 -#define FLASH_BUFFER_SIZE 4096 - -//Max filename length (8.3 plus a null char terminator) -#define FILENAME_STRING_SIZE 13 - -//State machine -#define STATE_START 0 -#define STATE_SIZE 1 -#define STATE_CONTENT 2 - -//Special bytes in the communication protocol -#define BYTE_START 0x7e -#define BYTE_ESCAPE 0x7d -#define BYTE_SEPARATOR 0x7c - -#define CSPIN 21 - -void setup(){ - Serial.begin(9600); // initialize Serial communication - while(!Serial) ; // wait for serial port to connect. - - pinMode(13, OUTPUT); - - SerialFlash.begin(CSPIN); - - //We start by formatting the flash... - uint8_t id[5]; - SerialFlash.readID(id); - SerialFlash.eraseAll(); - - //Flash LED at 1Hz while formatting - while (!SerialFlash.ready()) { - delay(500); - digitalWrite(13, HIGH); - delay(500); - digitalWrite(13, LOW); - } - - //Quickly flash LED a few times when completed, then leave the light on solid - for(uint8_t i = 0; i < 10; i++){ - delay(100); - digitalWrite(13, HIGH); - delay(100); - digitalWrite(13, LOW); - } - digitalWrite(13, HIGH); - - //We are now going to wait for the upload program - while(!Serial.available()); - - SerialFlashFile flashFile; - - uint8_t state = STATE_START; - uint8_t escape = 0; - uint8_t fileSizeIndex = 0; - uint32_t fileSize = 0; - char filename[FILENAME_STRING_SIZE]; - - char usbBuffer[USB_BUFFER_SIZE]; - uint8_t flashBuffer[FLASH_BUFFER_SIZE]; - - uint16_t flashBufferIndex = 0; - uint8_t filenameIndex = 0; - - uint32_t lastReceiveTime = millis(); - - //We assume the serial receive part is finished when we have not received something for 3 seconds - while(Serial.available() || lastReceiveTime + 3000 > millis()){ - uint16_t available = Serial.readBytes(usbBuffer, USB_BUFFER_SIZE); - if (available){ - lastReceiveTime = millis(); - } - - for (uint16_t usbBufferIndex = 0; usbBufferIndex < available; usbBufferIndex++){ - uint8_t b = usbBuffer[usbBufferIndex]; - - if (state == STATE_START){ - //Start byte. Repeat start is fine. - if (b == BYTE_START){ - for (uint8_t i = 0; i < FILENAME_STRING_SIZE; i++){ - filename[i] = 0x00; - } - filenameIndex = 0; - } - //Valid characters are A-Z, 0-9, comma, period, colon, dash, underscore - else if ((b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9') || b == '.' || b == ',' || b == ':' || b == '-' || b == '_'){ - filename[filenameIndex++] = b; - if (filenameIndex >= FILENAME_STRING_SIZE){ - //Error name too long - flushError(); - return; - } - } - //Filename end character - else if (b == BYTE_SEPARATOR){ - if (filenameIndex == 0){ - //Error empty filename - flushError(); - return; - } - - //Change state - state = STATE_SIZE; - fileSizeIndex = 0; - fileSize = 0; - - } - //Invalid character - else { - //Error bad filename - flushError(); - return; - } - } - //We read 4 bytes as a uint32_t for file size - else if (state == STATE_SIZE){ - if (fileSizeIndex < 4){ - fileSize = (fileSize << 8) + b; - fileSizeIndex++; - } - else if (b == BYTE_SEPARATOR){ - state = STATE_CONTENT; - flashBufferIndex = 0; - escape = 0; - - if (SerialFlash.exists(filename)){ - SerialFlash.remove(filename); //It doesn't reclaim the space, but it does let you create a new file with the same name. - } - - //Create a new file and open it for writing - if (SerialFlash.create(filename, fileSize)) { - flashFile = SerialFlash.open(filename); - if (!flashFile) { - //Error flash file open - flushError(); - return; - } - } - else { - //Error flash create (no room left?) - flushError(); - return; - } - } - else { - //Error invalid length requested - flushError(); - return; - } - } - else if (state == STATE_CONTENT){ - //Previous byte was escaped; unescape and add to buffer - if (escape){ - escape = 0; - flashBuffer[flashBufferIndex++] = b ^ 0x20; - } - //Escape the next byte - else if (b == BYTE_ESCAPE){ - //Serial.println("esc"); - escape = 1; - } - //End of file - else if (b == BYTE_START){ - //Serial.println("End of file"); - state = STATE_START; - flashFile.write(flashBuffer, flashBufferIndex); - flashFile.close(); - flashBufferIndex = 0; - } - //Normal byte; add to buffer - else { - flashBuffer[flashBufferIndex++] = b; - } - - //The buffer is filled; write to SD card - if (flashBufferIndex >= FLASH_BUFFER_SIZE){ - flashFile.write(flashBuffer, FLASH_BUFFER_SIZE); - flashBufferIndex = 0; - } - } - } - } - - //Success! Turn the light off. - digitalWrite(13, LOW); -} - -void loop(){ - //Do nothing. -} - -void flushError(){ - uint32_t lastReceiveTime = millis(); - char usbBuffer[USB_BUFFER_SIZE]; - //We assume the serial receive part is finished when we have not received something for 3 seconds - while(Serial.available() || lastReceiveTime + 3000 > millis()){ - if (Serial.readBytes(usbBuffer, USB_BUFFER_SIZE)){ - lastReceiveTime = millis(); - } - } -} diff --git a/libraries/SerialFlash/examples/EraseEverything/EraseEverything.ino b/libraries/SerialFlash/examples/EraseEverything/EraseEverything.ino deleted file mode 100644 index d3b3f4d7..00000000 --- a/libraries/SerialFlash/examples/EraseEverything/EraseEverything.ino +++ /dev/null @@ -1,80 +0,0 @@ -//SerialFlash library API: https://github.com/PaulStoffregen/SerialFlash - -#include -#include - -const int FlashChipSelect = 21; // digital pin for flash chip CS pin - -SerialFlashFile file; - -const unsigned long testIncrement = 4096; - -void setup() { - //uncomment these if using Teensy audio shield - //SPI.setSCK(14); // Audio shield has SCK on pin 14 - //SPI.setMOSI(7); // Audio shield has MOSI on pin 7 - - //uncomment these if you have other SPI chips connected - //to keep them disabled while using only SerialFlash - //pinMode(4, INPUT_PULLUP); - //pinMode(10, INPUT_PULLUP); - - Serial.begin(9600); - - // wait up to 10 seconds for Arduino Serial Monitor - unsigned long startMillis = millis(); - while (!Serial && (millis() - startMillis < 10000)) ; - delay(100); - - SerialFlash.begin(FlashChipSelect); - unsigned char id[5]; - SerialFlash.readID(id); - unsigned long size = SerialFlash.capacity(id); - - if (size > 0) { - Serial.print("Flash Memory has "); - Serial.print(size); - Serial.println(" bytes."); - Serial.println("Erasing ALL Flash Memory:"); - // Estimate the (lengthy) wait time. - Serial.print(" estimated wait: "); - int seconds = (float)size / eraseBytesPerSecond(id) + 0.5; - Serial.print(seconds); - Serial.println(" seconds."); - Serial.println(" Yes, full chip erase is SLOW!"); - SerialFlash.eraseAll(); - unsigned long dotMillis = millis(); - unsigned char dotcount = 0; - while (SerialFlash.ready() == false) { - if (millis() - dotMillis > 1000) { - dotMillis = dotMillis + 1000; - Serial.print("."); - dotcount = dotcount + 1; - if (dotcount >= 60) { - Serial.println(); - dotcount = 0; - } - } - } - if (dotcount > 0) Serial.println(); - Serial.println("Erase completed"); - unsigned long elapsed = millis() - startMillis; - Serial.print(" actual wait: "); - Serial.print(elapsed / 1000ul); - Serial.println(" seconds."); - } -} - -float eraseBytesPerSecond(const unsigned char *id) { - if (id[0] == 0x20) return 152000.0; // Micron - if (id[0] == 0x01) return 500000.0; // Spansion - if (id[0] == 0xEF) return 419430.0; // Winbond - if (id[0] == 0xC2) return 279620.0; // Macronix - return 320000.0; // guess? -} - - -void loop() { - -} - diff --git a/libraries/SerialFlash/examples/FileWrite/FileWrite.ino b/libraries/SerialFlash/examples/FileWrite/FileWrite.ino deleted file mode 100755 index dbeb438a..00000000 --- a/libraries/SerialFlash/examples/FileWrite/FileWrite.ino +++ /dev/null @@ -1,50 +0,0 @@ -//SerialFlash library API: https://github.com/PaulStoffregen/SerialFlash - -#include -#include - -#define FSIZE 256 - -const char *filename = "myfile.txt"; -const char *contents = "0123456789ABCDEF"; - -const int FlashChipSelect = 21; // digital pin for flash chip CS pin - -void setup() { - Serial.begin(9600); - - // wait for Arduino Serial Monitor - while (!Serial) ; - delay(100); - - // Init. SPI Flash chip - if (!SerialFlash.begin(FlashChipSelect)) { - Serial.println("Unable to access SPI Flash chip"); - } - - SerialFlashFile file; - - // Create the file if it doesn't exist - if (!create_if_not_exists(filename)) { - Serial.println("Not enough space to create file " + String(filename)); - return; - } - - // Open the file and write test data - file = SerialFlash.open(filename); - file.write(contents, strlen(contents) + 1); - Serial.println("String \"" + String(contents) + "\" written to file " + String(filename)); -} - -bool create_if_not_exists (const char *filename) { - if (!SerialFlash.exists(filename)) { - Serial.println("Creating file " + String(filename)); - return SerialFlash.create(filename, FSIZE); - } - - Serial.println("File " + String(filename) + " already exists"); - return true; -} - -void loop() { -} diff --git a/libraries/SerialFlash/examples/ListFiles/ListFiles.ino b/libraries/SerialFlash/examples/ListFiles/ListFiles.ino deleted file mode 100644 index bc15b89b..00000000 --- a/libraries/SerialFlash/examples/ListFiles/ListFiles.ino +++ /dev/null @@ -1,63 +0,0 @@ -// SerialFlash library API: https://github.com/PaulStoffregen/SerialFlash - -#include -#include - -const int FlashChipSelect = 21; // digital pin for flash chip CS pin - -void setup() { - //uncomment these if using Teensy audio shield - //SPI.setSCK(14); // Audio shield has SCK on pin 14 - //SPI.setMOSI(7); // Audio shield has MOSI on pin 7 - - //uncomment these if you have other SPI chips connected - //to keep them disabled while using only SerialFlash - //pinMode(4, INPUT_PULLUP); - //pinMode(10, INPUT_PULLUP); - - Serial.begin(9600); - - // wait for Arduino Serial Monitor - while (!Serial) ; - delay(100); - Serial.println("All Files on SPI Flash chip:"); - - if (!SerialFlash.begin(FlashChipSelect)) { - error("Unable to access SPI Flash chip"); - } - - SerialFlash.opendir(); - unsigned int count = 0; - while (1) { - char filename[64]; - unsigned long filesize; - - if (SerialFlash.readdir(filename, sizeof(filename), filesize)) { - Serial.print(" "); - Serial.print(filename); - spaces(20 - strlen(filename)); - Serial.print(" "); - Serial.print(filesize); - Serial.print(" bytes"); - Serial.println(); - } else { - break; // no more files - } - } -} - -void spaces(int num) { - for (int i=0; i < num; i++) { - Serial.print(" "); - } -} - -void loop() { -} - -void error(const char *message) { - while (1) { - Serial.println(message); - delay(2500); - } -} diff --git a/libraries/SerialFlash/examples/RawHardwareTest/RawHardwareTest.ino b/libraries/SerialFlash/examples/RawHardwareTest/RawHardwareTest.ino deleted file mode 100644 index 74afa10a..00000000 --- a/libraries/SerialFlash/examples/RawHardwareTest/RawHardwareTest.ino +++ /dev/null @@ -1,502 +0,0 @@ -// SerialFlash library API: https://github.com/PaulStoffregen/SerialFlash -// -// RawHardwareTest - Check if a SPI Flash chip is compatible -// with SerialFlash by performing many read and write tests -// to its memory. -// -// The chip should be fully erased before running this test. -// Use the EraseEverything to do a (slow) full chip erase. -// -// Normally you should NOT access the flash memory directly, -// as this test program does. You should create files and -// read and write the files. File creation allocates space -// with program & erase boundaries within the chip, to allow -// reading from any other files while a file is busy writing -// or erasing (if created as erasable). -// -// If you discover an incompatible chip, please report it here: -// https://github.com/PaulStoffregen/SerialFlash/issues -// You MUST post the complete output of this program, and -// the exact part number and manufacturer of the chip. - - -#include -#include - -const int FlashChipSelect = 21; // digital pin for flash chip CS pin - -SerialFlashFile file; - -const unsigned long testIncrement = 4096; - -void setup() { - - //uncomment these if using Teensy audio shield - //SPI.setSCK(14); // Audio shield has SCK on pin 14 - //SPI.setMOSI(7); // Audio shield has MOSI on pin 7 - - //uncomment these if you have other SPI chips connected - //to keep them disabled while using only SerialFlash - //pinMode(4, INPUT_PULLUP); - //pinMode(10, INPUT_PULLUP); - - Serial.begin(9600); - - while (!Serial) ; - delay(100); - - Serial.println("Raw SerialFlash Hardware Test"); - SerialFlash.begin(FlashChipSelect); - - if (test()) { - Serial.println(); - Serial.println("All Tests Passed :-)"); - Serial.println(); - Serial.println("Test data was written to your chip. You must run"); - Serial.println("EraseEverything before using this chip for files."); - } else { - Serial.println(); - Serial.println("Tests Failed :{"); - Serial.println(); - Serial.println("The flash chip may be left in an improper state."); - Serial.println("You might need to power cycle to return to normal."); - } -} - - -bool test() { - unsigned char buf[256], sig[256], buf2[8]; - unsigned long address, count, chipsize, blocksize; - unsigned long usec; - bool first; - - // Read the chip identification - Serial.println(); - Serial.println("Read Chip Identification:"); - SerialFlash.readID(buf); - Serial.print(" JEDEC ID: "); - Serial.print(buf[0], HEX); - Serial.print(" "); - Serial.print(buf[1], HEX); - Serial.print(" "); - Serial.println(buf[2], HEX); - Serial.print(" Part Nummber: "); - Serial.println(id2chip(buf)); - Serial.print(" Memory Size: "); - chipsize = SerialFlash.capacity(buf); - Serial.print(chipsize); - Serial.println(" bytes"); - if (chipsize == 0) return false; - Serial.print(" Block Size: "); - blocksize = SerialFlash.blockSize(); - Serial.print(blocksize); - Serial.println(" bytes"); - - - // Read the entire chip. Every test location must be - // erased, or have a previously tested signature - Serial.println(); - Serial.println("Reading Chip..."); - memset(buf, 0, sizeof(buf)); - memset(sig, 0, sizeof(sig)); - memset(buf2, 0, sizeof(buf2)); - address = 0; - count = 0; - first = true; - while (address < chipsize) { - SerialFlash.read(address, buf, 8); - //Serial.print(" addr = "); - //Serial.print(address, HEX); - //Serial.print(", data = "); - //printbuf(buf, 8); - create_signature(address, sig); - if (is_erased(buf, 8) == false) { - if (equal_signatures(buf, sig) == false) { - Serial.print(" Previous data found at address "); - Serial.println(address); - Serial.println(" You must fully erase the chip before this test"); - Serial.print(" found this: "); - printbuf(buf, 8); - Serial.print(" correct: "); - printbuf(sig, 8); - return false; - } - } else { - count = count + 1; // number of blank signatures - } - if (first) { - address = address + (testIncrement - 8); - first = false; - } else { - address = address + 8; - first = true; - } - } - - - // Write any signatures that were blank on the original check - if (count > 0) { - Serial.println(); - Serial.print("Writing "); - Serial.print(count); - Serial.println(" signatures"); - memset(buf, 0, sizeof(buf)); - memset(sig, 0, sizeof(sig)); - memset(buf2, 0, sizeof(buf2)); - address = 0; - first = true; - while (address < chipsize) { - SerialFlash.read(address, buf, 8); - if (is_erased(buf, 8)) { - create_signature(address, sig); - //Serial.printf("write %08X: data: ", address); - //printbuf(sig, 8); - SerialFlash.write(address, sig, 8); - while (!SerialFlash.ready()) ; // wait - SerialFlash.read(address, buf, 8); - if (equal_signatures(buf, sig) == false) { - Serial.print(" error writing signature at "); - Serial.println(address); - Serial.print(" Read this: "); - printbuf(buf, 8); - Serial.print(" Expected: "); - printbuf(sig, 8); - return false; - } - } - if (first) { - address = address + (testIncrement - 8); - first = false; - } else { - address = address + 8; - first = true; - } - } - } else { - Serial.println(" all signatures present from prior tests"); - } - - - // Read all the signatures again, just to be sure - // checks prior writing didn't corrupt any other data - Serial.println(); - Serial.println("Double Checking All Signatures:"); - memset(buf, 0, sizeof(buf)); - memset(sig, 0, sizeof(sig)); - memset(buf2, 0, sizeof(buf2)); - count = 0; - address = 0; - first = true; - while (address < chipsize) { - SerialFlash.read(address, buf, 8); - create_signature(address, sig); - if (equal_signatures(buf, sig) == false) { - Serial.print(" error in signature at "); - Serial.println(address); - Serial.print(" Read this: "); - printbuf(buf, 8); - Serial.print(" Expected: "); - printbuf(sig, 8); - return false; - } - count = count + 1; - if (first) { - address = address + (testIncrement - 8); - first = false; - } else { - address = address + 8; - first = true; - } - } - Serial.print(" all "); - Serial.print(count); - Serial.println(" signatures read ok"); - - - // Read pairs of adjacent signatures - // check read works across boundaries - Serial.println(); - Serial.println("Checking Signature Pairs"); - memset(buf, 0, sizeof(buf)); - memset(sig, 0, sizeof(sig)); - memset(buf2, 0, sizeof(buf2)); - count = 0; - address = testIncrement - 8; - first = true; - while (address < chipsize - 8) { - SerialFlash.read(address, buf, 16); - create_signature(address, sig); - create_signature(address + 8, sig + 8); - if (memcmp(buf, sig, 16) != 0) { - Serial.print(" error in signature pair at "); - Serial.println(address); - Serial.print(" Read this: "); - printbuf(buf, 16); - Serial.print(" Expected: "); - printbuf(sig, 16); - return false; - } - count = count + 1; - address = address + testIncrement; - } - Serial.print(" all "); - Serial.print(count); - Serial.println(" signature pairs read ok"); - - - // Write data and read while write in progress - Serial.println(); - Serial.println("Checking Read-While-Write (Program Suspend)"); - address = 256; - while (address < chipsize) { // find a blank space - SerialFlash.read(address, buf, 256); - if (is_erased(buf, 256)) break; - address = address + 256; - } - if (address >= chipsize) { - Serial.println(" error, unable to find any blank space!"); - return false; - } - for (int i=0; i < 256; i += 8) { - create_signature(address + i, sig + i); - } - Serial.print(" write 256 bytes at "); - Serial.println(address); - Serial.flush(); - SerialFlash.write(address, sig, 256); - usec = micros(); - if (SerialFlash.ready()) { - Serial.println(" error, chip did not become busy after write"); - return false; - } - SerialFlash.read(0, buf2, 8); // read while busy writing - while (!SerialFlash.ready()) ; // wait - usec = micros() - usec; - Serial.print(" write time was "); - Serial.print(usec); - Serial.println(" microseconds."); - SerialFlash.read(address, buf, 256); - if (memcmp(buf, sig, 256) != 0) { - Serial.println(" error writing to flash"); - Serial.print(" Read this: "); - printbuf(buf, 256); - Serial.print(" Expected: "); - printbuf(sig, 256); - return false; - } - create_signature(0, sig); - if (memcmp(buf2, sig, 8) != 0) { - Serial.println(" error, incorrect read while writing"); - Serial.print(" Read this: "); - printbuf(buf2, 256); - Serial.print(" Expected: "); - printbuf(sig, 256); - return false; - } - Serial.print(" read-while-writing: "); - printbuf(buf2, 8); - Serial.println(" test passed, good read while writing"); - - - - // Erase a block and read while erase in progress - if (chipsize >= 262144 + blocksize + testIncrement) { - Serial.println(); - Serial.println("Checking Read-While-Erase (Erase Suspend)"); - memset(buf, 0, sizeof(buf)); - memset(sig, 0, sizeof(sig)); - memset(buf2, 0, sizeof(buf2)); - SerialFlash.eraseBlock(262144); - usec = micros(); - delayMicroseconds(50); - if (SerialFlash.ready()) { - Serial.println(" error, chip did not become busy after erase"); - return false; - } - SerialFlash.read(0, buf2, 8); // read while busy writing - while (!SerialFlash.ready()) ; // wait - usec = micros() - usec; - Serial.print(" erase time was "); - Serial.print(usec); - Serial.println(" microseconds."); - // read all signatures, check ones in this block got - // erased, and all the others are still intact - address = 0; - first = true; - while (address < chipsize) { - SerialFlash.read(address, buf, 8); - if (address >= 262144 && address < 262144 + blocksize) { - if (is_erased(buf, 8) == false) { - Serial.print(" error in erasing at "); - Serial.println(address); - Serial.print(" Read this: "); - printbuf(buf, 8); - return false; - } - } else { - create_signature(address, sig); - if (equal_signatures(buf, sig) == false) { - Serial.print(" error in signature at "); - Serial.println(address); - Serial.print(" Read this: "); - printbuf(buf, 8); - Serial.print(" Expected: "); - printbuf(sig, 8); - return false; - } - } - if (first) { - address = address + (testIncrement - 8); - first = false; - } else { - address = address + 8; - first = true; - } - } - Serial.print(" erase correctly erased "); - Serial.print(blocksize); - Serial.println(" bytes"); - // now check if the data we read during erase is good - create_signature(0, sig); - if (memcmp(buf2, sig, 8) != 0) { - Serial.println(" error, incorrect read while erasing"); - Serial.print(" Read this: "); - printbuf(buf2, 256); - Serial.print(" Expected: "); - printbuf(sig, 256); - return false; - } - Serial.print(" read-while-erasing: "); - printbuf(buf2, 8); - Serial.println(" test passed, good read while erasing"); - - } else { - Serial.println("Skip Read-While-Erase, this chip is too small"); - } - - - - - return true; -} - - -void loop() { - // do nothing after the test -} - -const char * id2chip(const unsigned char *id) -{ - if (id[0] == 0xEF) { - // Winbond - if (id[1] == 0x40) { - if (id[2] == 0x14) return "W25Q80BV"; - if (id[2] == 0x15) return "W25Q16DV"; - if (id[2] == 0x17) return "W25Q64FV"; - if (id[2] == 0x18) return "W25Q128FV"; - if (id[2] == 0x19) return "W25Q256FV"; - } - } - if (id[0] == 0x01) { - // Spansion - if (id[1] == 0x02) { - if (id[2] == 0x16) return "S25FL064A"; - if (id[2] == 0x19) return "S25FL256S"; - if (id[2] == 0x20) return "S25FL512S"; - } - if (id[1] == 0x20) { - if (id[2] == 0x18) return "S25FL127S"; - } - } - if (id[0] == 0xC2) { - // Macronix - if (id[1] == 0x20) { - if (id[2] == 0x18) return "MX25L12805D"; - } - } - if (id[0] == 0x20) { - // Micron - if (id[1] == 0xBA) { - if (id[2] == 0x20) return "N25Q512A"; - if (id[2] == 0x21) return "N25Q00AA"; - } - if (id[1] == 0xBB) { - if (id[2] == 0x22) return "MT25QL02GC"; - } - } - if (id[0] == 0xBF) { - // SST - if (id[1] == 0x25) { - if (id[2] == 0x02) return "SST25WF010"; - if (id[2] == 0x03) return "SST25WF020"; - if (id[2] == 0x04) return "SST25WF040"; - if (id[2] == 0x41) return "SST25VF016B"; - if (id[2] == 0x4A) return "SST25VF032"; - } - if (id[1] == 0x25) { - if (id[2] == 0x01) return "SST26VF016"; - if (id[2] == 0x02) return "SST26VF032"; - if (id[2] == 0x43) return "SST26VF064"; - } - } - return "(unknown chip)"; -} - -void print_signature(const unsigned char *data) -{ - Serial.print("data="); - for (unsigned char i=0; i < 8; i++) { - Serial.print(data[i]); - Serial.print(" "); - } - Serial.println(); -} - -void create_signature(unsigned long address, unsigned char *data) -{ - data[0] = address >> 24; - data[1] = address >> 16; - data[2] = address >> 8; - data[3] = address; - unsigned long hash = 2166136261ul; - for (unsigned char i=0; i < 4; i++) { - hash ^= data[i]; - hash *= 16777619ul; - } - data[4] = hash; - data[5] = hash >> 8; - data[6] = hash >> 16; - data[7] = hash >> 24; -} - -bool equal_signatures(const unsigned char *data1, const unsigned char *data2) -{ - for (unsigned char i=0; i < 8; i++) { - if (data1[i] != data2[i]) return false; - } - return true; -} - -bool is_erased(const unsigned char *data, unsigned int len) -{ - while (len > 0) { - if (*data++ != 255) return false; - len = len - 1; - } - return true; -} - - -void printbuf(const void *buf, uint32_t len) -{ - const uint8_t *p = (const uint8_t *)buf; - do { - unsigned char b = *p++; - Serial.print(b >> 4, HEX); - Serial.print(b & 15, HEX); - //Serial.printf("%02X", *p++); - Serial.print(" "); - } while (--len > 0); - Serial.println(); -} - diff --git a/libraries/SerialFlash/keywords.txt b/libraries/SerialFlash/keywords.txt deleted file mode 100644 index 1e473961..00000000 --- a/libraries/SerialFlash/keywords.txt +++ /dev/null @@ -1,9 +0,0 @@ -SerialFlash KEYWORD1 -SerialFlashFile KEYWORD1 -createWritable KEYWORD2 -erase KEYWORD2 -eraseAll KEYWORD2 -ready KEYWORD2 -create KEYWORD2 -createWritable KEYWORD2 -getAddress KEYWORD2 diff --git a/libraries/SerialFlash/util/SerialFlash_directwrite.h b/libraries/SerialFlash/util/SerialFlash_directwrite.h deleted file mode 100644 index d323a055..00000000 --- a/libraries/SerialFlash/util/SerialFlash_directwrite.h +++ /dev/null @@ -1,204 +0,0 @@ -#ifndef SerialFlash_directwrite_h -#define SerialFlash_directwrite_h - -#include - -// Adapted from OneWire.h - -#if ARDUINO >= 100 -#include "Arduino.h" // for delayMicroseconds, digitalPinToBitMask, etc -#else -#include "WProgram.h" // for delayMicroseconds -#include "pins_arduino.h" // for digitalPinToBitMask, etc -#endif - -// Platform specific I/O definitions - -#if defined(__AVR__) -#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin))) -#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) -#define IO_REG_TYPE uint8_t -#define IO_REG_ASM asm("r30") -#define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0) -#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) &= ~(mask)) -#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+1)) |= (mask)) -#define DIRECT_WRITE_LOW(base, mask) ((*((base)+2)) &= ~(mask)) -#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+2)) |= (mask)) - -#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK66FX1M0__) || defined(__MK64FX512__) -#define PIN_TO_BASEREG(pin) (portOutputRegister(pin)) -#define PIN_TO_BITMASK(pin) (1) -#define IO_REG_TYPE uint8_t -#define IO_REG_ASM -#define DIRECT_READ(base, mask) (*((base)+512)) -#define DIRECT_MODE_INPUT(base, mask) (*((base)+640) = 0) -#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+640) = 1) -#define DIRECT_WRITE_LOW(base, mask) (*((base)+256) = 1) -#define DIRECT_WRITE_HIGH(base, mask) (*((base)+128) = 1) - -#elif defined(__MKL26Z64__) -#define PIN_TO_BASEREG(pin) (portOutputRegister(pin)) -#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) -#define IO_REG_TYPE uint8_t -#define IO_REG_ASM -#define DIRECT_READ(base, mask) ((*((base)+16) & (mask)) ? 1 : 0) -#define DIRECT_MODE_INPUT(base, mask) (*((base)+20) &= ~(mask)) -#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+20) |= (mask)) -#define DIRECT_WRITE_LOW(base, mask) (*((base)+8) = (mask)) -#define DIRECT_WRITE_HIGH(base, mask) (*((base)+4) = (mask)) - -#elif defined(__SAM3X8E__) -#define PIN_TO_BASEREG(pin) (&(digitalPinToPort(pin)->PIO_PER)) -#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) -#define IO_REG_TYPE uint32_t -#define IO_REG_ASM -#define DIRECT_READ(base, mask) (((*((base)+15)) & (mask)) ? 1 : 0) -#define DIRECT_MODE_INPUT(base, mask) ((*((base)+5)) = (mask)) -#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+4)) = (mask)) -#define DIRECT_WRITE_LOW(base, mask) ((*((base)+13)) = (mask)) -#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+12)) = (mask)) -#ifndef PROGMEM -#define PROGMEM -#endif -#ifndef pgm_read_byte -#define pgm_read_byte(addr) (*(const uint8_t *)(addr)) -#endif - -#elif defined(__PIC32MX__) -#define PIN_TO_BASEREG(pin) (portModeRegister(digitalPinToPort(pin))) -#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) -#define IO_REG_TYPE uint32_t -#define IO_REG_ASM -#define DIRECT_READ(base, mask) (((*(base+4)) & (mask)) ? 1 : 0) //PORTX + 0x10 -#define DIRECT_MODE_INPUT(base, mask) ((*(base+2)) = (mask)) //TRISXSET + 0x08 -#define DIRECT_MODE_OUTPUT(base, mask) ((*(base+1)) = (mask)) //TRISXCLR + 0x04 -#define DIRECT_WRITE_LOW(base, mask) ((*(base+8+1)) = (mask)) //LATXCLR + 0x24 -#define DIRECT_WRITE_HIGH(base, mask) ((*(base+8+2)) = (mask)) //LATXSET + 0x28 - -#elif defined(ARDUINO_ARCH_ESP8266) -#define PIN_TO_BASEREG(pin) ((volatile uint32_t*) GPO) -#define PIN_TO_BITMASK(pin) (1 << pin) -#define IO_REG_TYPE uint32_t -#define IO_REG_ASM -#define DIRECT_READ(base, mask) ((GPI & (mask)) ? 1 : 0) //GPIO_IN_ADDRESS -#define DIRECT_MODE_INPUT(base, mask) (GPE &= ~(mask)) //GPIO_ENABLE_W1TC_ADDRESS -#define DIRECT_MODE_OUTPUT(base, mask) (GPE |= (mask)) //GPIO_ENABLE_W1TS_ADDRESS -#define DIRECT_WRITE_LOW(base, mask) (GPOC = (mask)) //GPIO_OUT_W1TC_ADDRESS -#define DIRECT_WRITE_HIGH(base, mask) (GPOS = (mask)) //GPIO_OUT_W1TS_ADDRESS - -#elif defined(__SAMD21G18A__) -#define PIN_TO_BASEREG(pin) portModeRegister(digitalPinToPort(pin)) -#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) -#define IO_REG_TYPE uint32_t -#define IO_REG_ASM -#define DIRECT_READ(base, mask) (((*((base)+8)) & (mask)) ? 1 : 0) -#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) = (mask)) -#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+2)) = (mask)) -#define DIRECT_WRITE_LOW(base, mask) ((*((base)+5)) = (mask)) -#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+6)) = (mask)) - -#elif defined(RBL_NRF51822) -#define PIN_TO_BASEREG(pin) (0) -#define PIN_TO_BITMASK(pin) (pin) -#define IO_REG_TYPE uint32_t -#define IO_REG_ASM -#define DIRECT_READ(base, pin) nrf_gpio_pin_read(pin) -#define DIRECT_WRITE_LOW(base, pin) nrf_gpio_pin_clear(pin) -#define DIRECT_WRITE_HIGH(base, pin) nrf_gpio_pin_set(pin) -#define DIRECT_MODE_INPUT(base, pin) nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL) -#define DIRECT_MODE_OUTPUT(base, pin) nrf_gpio_cfg_output(pin) - -#elif defined(__arc__) /* Arduino101/Genuino101 specifics */ - -#include "scss_registers.h" -#include "portable.h" -#include "avr/pgmspace.h" - -#define GPIO_ID(pin) (g_APinDescription[pin].ulGPIOId) -#define GPIO_TYPE(pin) (g_APinDescription[pin].ulGPIOType) -#define GPIO_BASE(pin) (g_APinDescription[pin].ulGPIOBase) -#define DIR_OFFSET_SS 0x01 -#define DIR_OFFSET_SOC 0x04 -#define EXT_PORT_OFFSET_SS 0x0A -#define EXT_PORT_OFFSET_SOC 0x50 - -/* GPIO registers base address */ -#define PIN_TO_BASEREG(pin) ((volatile uint32_t *)g_APinDescription[pin].ulGPIOBase) -#define PIN_TO_BITMASK(pin) pin -#define IO_REG_TYPE uint32_t -#define IO_REG_ASM - -static inline __attribute__((always_inline)) -IO_REG_TYPE directRead(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) -{ - IO_REG_TYPE ret; - if (SS_GPIO == GPIO_TYPE(pin)) { - ret = READ_ARC_REG(((IO_REG_TYPE)base + EXT_PORT_OFFSET_SS)); - } else { - ret = MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, EXT_PORT_OFFSET_SOC); - } - return ((ret >> GPIO_ID(pin)) & 0x01); -} - -static inline __attribute__((always_inline)) -void directModeInput(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) -{ - if (SS_GPIO == GPIO_TYPE(pin)) { - WRITE_ARC_REG(READ_ARC_REG((((IO_REG_TYPE)base) + DIR_OFFSET_SS)) & ~(0x01 << GPIO_ID(pin)), - ((IO_REG_TYPE)(base) + DIR_OFFSET_SS)); - } else { - MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) &= ~(0x01 << GPIO_ID(pin)); - } -} - -static inline __attribute__((always_inline)) -void directModeOutput(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) -{ - if (SS_GPIO == GPIO_TYPE(pin)) { - WRITE_ARC_REG(READ_ARC_REG(((IO_REG_TYPE)(base) + DIR_OFFSET_SS)) | (0x01 << GPIO_ID(pin)), - ((IO_REG_TYPE)(base) + DIR_OFFSET_SS)); - } else { - MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) |= (0x01 << GPIO_ID(pin)); - } -} - -static inline __attribute__((always_inline)) -void directWriteLow(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) -{ - if (SS_GPIO == GPIO_TYPE(pin)) { - WRITE_ARC_REG(READ_ARC_REG(base) & ~(0x01 << GPIO_ID(pin)), base); - } else { - MMIO_REG_VAL(base) &= ~(0x01 << GPIO_ID(pin)); - } -} - -static inline __attribute__((always_inline)) -void directWriteHigh(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) -{ - if (SS_GPIO == GPIO_TYPE(pin)) { - WRITE_ARC_REG(READ_ARC_REG(base) | (0x01 << GPIO_ID(pin)), base); - } else { - MMIO_REG_VAL(base) |= (0x01 << GPIO_ID(pin)); - } -} - -#define DIRECT_READ(base, pin) directRead(base, pin) -#define DIRECT_MODE_INPUT(base, pin) directModeInput(base, pin) -#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(base, pin) -#define DIRECT_WRITE_LOW(base, pin) directWriteLow(base, pin) -#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(base, pin) - -#else -#define PIN_TO_BASEREG(pin) (0) -#define PIN_TO_BITMASK(pin) (pin) -#define IO_REG_TYPE unsigned int -#define IO_REG_ASM -#define DIRECT_READ(base, pin) digitalRead(pin) -#define DIRECT_WRITE_LOW(base, pin) digitalWrite(pin, LOW) -#define DIRECT_WRITE_HIGH(base, pin) digitalWrite(pin, HIGH) -#define DIRECT_MODE_INPUT(base, pin) pinMode(pin,INPUT) -#define DIRECT_MODE_OUTPUT(base, pin) pinMode(pin,OUTPUT) - -#endif - -#endif