diff --git a/cores/esp8266/FS.h b/cores/esp8266/FS.h index e66fcd772..79dc319f0 100644 --- a/cores/esp8266/FS.h +++ b/cores/esp8266/FS.h @@ -21,8 +21,8 @@ #ifndef FS_H #define FS_H -#include #include +#include namespace fs { diff --git a/cores/esp8266/Print.cpp b/cores/esp8266/Print.cpp index 899bd83d9..5b481fd40 100644 --- a/cores/esp8266/Print.cpp +++ b/cores/esp8266/Print.cpp @@ -1,21 +1,21 @@ /* Print.cpp - Base class that provides print() and println() Copyright (c) 2008 David A. Mellis. All right reserved. - + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - + Modified 23 November 2006 by David A. Mellis Modified December 2014 by Ivan Grokhotkov Modified May 2015 by Michael C. Miller - esp8266 progmem support @@ -25,18 +25,14 @@ #include #include #include -#include "Arduino.h" +#include #include "Print.h" -extern "C" { -#include "c_types.h" -#include "ets_sys.h" -} // Public Methods ////////////////////////////////////////////////////////////// /* default implementation: may be overridden */ -size_t ICACHE_FLASH_ATTR Print::write(const uint8_t *buffer, size_t size) { +size_t Print::write(const uint8_t *buffer, size_t size) { size_t n = 0; while(size--) { n += write(*buffer++); @@ -67,7 +63,7 @@ size_t Print::printf(const char *format, ...) { return len; } -size_t ICACHE_FLASH_ATTR Print::print(const __FlashStringHelper *ifsh) { +size_t Print::print(const __FlashStringHelper *ifsh) { PGM_P p = reinterpret_cast(ifsh); size_t n = 0; @@ -79,31 +75,31 @@ size_t ICACHE_FLASH_ATTR Print::print(const __FlashStringHelper *ifsh) { return n; } -size_t ICACHE_FLASH_ATTR Print::print(const String &s) { +size_t Print::print(const String &s) { return write(s.c_str(), s.length()); } -size_t ICACHE_FLASH_ATTR Print::print(const char str[]) { +size_t Print::print(const char str[]) { return write(str); } -size_t ICACHE_FLASH_ATTR Print::print(char c) { +size_t Print::print(char c) { return write(c); } -size_t ICACHE_FLASH_ATTR Print::print(unsigned char b, int base) { +size_t Print::print(unsigned char b, int base) { return print((unsigned long) b, base); } -size_t ICACHE_FLASH_ATTR Print::print(int n, int base) { +size_t Print::print(int n, int base) { return print((long) n, base); } -size_t ICACHE_FLASH_ATTR Print::print(unsigned int n, int base) { +size_t Print::print(unsigned int n, int base) { return print((unsigned long) n, base); } -size_t ICACHE_FLASH_ATTR Print::print(long n, int base) { +size_t Print::print(long n, int base) { if(base == 0) { return write(n); } else if(base == 10) { @@ -118,86 +114,86 @@ size_t ICACHE_FLASH_ATTR Print::print(long n, int base) { } } -size_t ICACHE_FLASH_ATTR Print::print(unsigned long n, int base) { +size_t Print::print(unsigned long n, int base) { if(base == 0) return write(n); else return printNumber(n, base); } -size_t ICACHE_FLASH_ATTR Print::print(double n, int digits) { +size_t Print::print(double n, int digits) { return printFloat(n, digits); } -size_t ICACHE_FLASH_ATTR Print::println(const __FlashStringHelper *ifsh) { +size_t Print::println(const __FlashStringHelper *ifsh) { size_t n = print(ifsh); n += println(); return n; } -size_t ICACHE_FLASH_ATTR Print::print(const Printable& x) { +size_t Print::print(const Printable& x) { return x.printTo(*this); } -size_t ICACHE_FLASH_ATTR Print::println(void) { +size_t Print::println(void) { return print("\r\n"); } -size_t ICACHE_FLASH_ATTR Print::println(const String &s) { +size_t Print::println(const String &s) { size_t n = print(s); n += println(); return n; } -size_t ICACHE_FLASH_ATTR Print::println(const char c[]) { +size_t Print::println(const char c[]) { size_t n = print(c); n += println(); return n; } -size_t ICACHE_FLASH_ATTR Print::println(char c) { +size_t Print::println(char c) { size_t n = print(c); n += println(); return n; } -size_t ICACHE_FLASH_ATTR Print::println(unsigned char b, int base) { +size_t Print::println(unsigned char b, int base) { size_t n = print(b, base); n += println(); return n; } -size_t ICACHE_FLASH_ATTR Print::println(int num, int base) { +size_t Print::println(int num, int base) { size_t n = print(num, base); n += println(); return n; } -size_t ICACHE_FLASH_ATTR Print::println(unsigned int num, int base) { +size_t Print::println(unsigned int num, int base) { size_t n = print(num, base); n += println(); return n; } -size_t ICACHE_FLASH_ATTR Print::println(long num, int base) { +size_t Print::println(long num, int base) { size_t n = print(num, base); n += println(); return n; } -size_t ICACHE_FLASH_ATTR Print::println(unsigned long num, int base) { +size_t Print::println(unsigned long num, int base) { size_t n = print(num, base); n += println(); return n; } -size_t ICACHE_FLASH_ATTR Print::println(double num, int digits) { +size_t Print::println(double num, int digits) { size_t n = print(num, digits); n += println(); return n; } -size_t ICACHE_FLASH_ATTR Print::println(const Printable& x) { +size_t Print::println(const Printable& x) { size_t n = print(x); n += println(); return n; @@ -205,7 +201,7 @@ size_t ICACHE_FLASH_ATTR Print::println(const Printable& x) { // Private Methods ///////////////////////////////////////////////////////////// -size_t ICACHE_FLASH_ATTR Print::printNumber(unsigned long n, uint8_t base) { +size_t Print::printNumber(unsigned long n, uint8_t base) { char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. char *str = &buf[sizeof(buf) - 1]; @@ -225,7 +221,7 @@ size_t ICACHE_FLASH_ATTR Print::printNumber(unsigned long n, uint8_t base) { return write(str); } -size_t ICACHE_FLASH_ATTR Print::printFloat(double number, uint8_t digits) { +size_t Print::printFloat(double number, uint8_t digits) { size_t n = 0; if(isnan(number)) diff --git a/cores/esp8266/Stream.cpp b/cores/esp8266/Stream.cpp index c44fc2487..a29388b2b 100644 --- a/cores/esp8266/Stream.cpp +++ b/cores/esp8266/Stream.cpp @@ -20,16 +20,13 @@ parsing functions based on TextFinder library by Michael Margolis */ -#include "Arduino.h" -#include "Stream.h" -extern "C" { -#include "c_types.h" -} +#include +#include #define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait #define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field // private method to read stream with timeout -int ICACHE_FLASH_ATTR Stream::timedRead() { +int Stream::timedRead() { int c; _startMillis = millis(); do { @@ -42,7 +39,7 @@ int ICACHE_FLASH_ATTR Stream::timedRead() { } // private method to peek stream with timeout -int ICACHE_FLASH_ATTR Stream::timedPeek() { +int Stream::timedPeek() { int c; _startMillis = millis(); do { @@ -56,7 +53,7 @@ int ICACHE_FLASH_ATTR Stream::timedPeek() { // returns peek of the next digit in the stream or -1 if timeout // discards non-numeric characters -int ICACHE_FLASH_ATTR Stream::peekNextDigit() { +int Stream::peekNextDigit() { int c; while(1) { c = timedPeek(); @@ -73,31 +70,31 @@ int ICACHE_FLASH_ATTR Stream::peekNextDigit() { // Public Methods ////////////////////////////////////////////////////////////// -void ICACHE_FLASH_ATTR Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait +void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait { _timeout = timeout; } // find returns true if the target string is found -bool ICACHE_FLASH_ATTR Stream::find(const char *target) { +bool Stream::find(const char *target) { return findUntil(target, (char*) ""); } // reads data from the stream until the target string of given length is found // returns true if target string is found, false if timed out -bool ICACHE_FLASH_ATTR Stream::find(const char *target, size_t length) { +bool Stream::find(const char *target, size_t length) { return findUntil(target, length, NULL, 0); } // as find but search ends if the terminator string is found -bool ICACHE_FLASH_ATTR Stream::findUntil(const char *target, const char *terminator) { +bool Stream::findUntil(const char *target, const char *terminator) { return findUntil(target, strlen(target), terminator, strlen(terminator)); } // reads data from the stream until the target string of the given length is found // search terminated if the terminator string is found // returns true if target string is found, false if terminated or timed out -bool ICACHE_FLASH_ATTR Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen) { +bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen) { size_t index = 0; // maximum target string length is 64k bytes! size_t termIndex = 0; int c; @@ -128,13 +125,13 @@ bool ICACHE_FLASH_ATTR Stream::findUntil(const char *target, size_t targetLen, c // returns the first valid (long) integer value from the current position. // initial characters that are not digits (or the minus sign) are skipped // function is terminated by the first character that is not a digit. -long ICACHE_FLASH_ATTR Stream::parseInt() { +long Stream::parseInt() { return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout) } // as above but a given skipChar is ignored // this allows format characters (typically commas) in values to be ignored -long ICACHE_FLASH_ATTR Stream::parseInt(char skipChar) { +long Stream::parseInt(char skipChar) { boolean isNegative = false; long value = 0; int c; @@ -161,13 +158,13 @@ long ICACHE_FLASH_ATTR Stream::parseInt(char skipChar) { } // as parseInt but returns a floating point value -float ICACHE_FLASH_ATTR Stream::parseFloat() { +float Stream::parseFloat() { return parseFloat(NO_SKIP_CHAR); } // as above but the given skipChar is ignored // this allows format characters (typically commas) in values to be ignored -float ICACHE_FLASH_ATTR Stream::parseFloat(char skipChar) { +float Stream::parseFloat(char skipChar) { boolean isNegative = false; boolean isFraction = false; long value = 0; @@ -208,7 +205,7 @@ float ICACHE_FLASH_ATTR Stream::parseFloat(char skipChar) { // returns the number of characters placed in the buffer // the buffer is NOT null terminated. // -size_t ICACHE_FLASH_ATTR Stream::readBytes(char *buffer, size_t length) { +size_t Stream::readBytes(char *buffer, size_t length) { size_t count = 0; while(count < length) { int c = timedRead(); @@ -224,7 +221,7 @@ size_t ICACHE_FLASH_ATTR Stream::readBytes(char *buffer, size_t length) { // terminates if length characters have been read, timeout, or if the terminator character detected // returns the number of characters placed in the buffer (0 means no valid data found) -size_t ICACHE_FLASH_ATTR Stream::readBytesUntil(char terminator, char *buffer, size_t length) { +size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) { if(length < 1) return 0; size_t index = 0; @@ -238,7 +235,7 @@ size_t ICACHE_FLASH_ATTR Stream::readBytesUntil(char terminator, char *buffer, s return index; // return number of characters, not including null terminator } -String ICACHE_FLASH_ATTR Stream::readString() { +String Stream::readString() { String ret; int c = timedRead(); while(c >= 0) { @@ -248,7 +245,7 @@ String ICACHE_FLASH_ATTR Stream::readString() { return ret; } -String ICACHE_FLASH_ATTR Stream::readStringUntil(char terminator) { +String Stream::readStringUntil(char terminator) { String ret; int c = timedRead(); while(c >= 0 && c != terminator) { diff --git a/cores/esp8266/WString.cpp b/cores/esp8266/WString.cpp index 5e7b3fcc9..c66f5da95 100644 --- a/cores/esp8266/WString.cpp +++ b/cores/esp8266/WString.cpp @@ -21,48 +21,43 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include "WString.h" #include "stdlib_noniso.h" -extern "C" { -#include "osapi.h" -#include "ets_sys.h" -#include "mem.h" -#include "c_types.h" -} /*********************************************/ /* Constructors */ /*********************************************/ -ICACHE_FLASH_ATTR String::String(const char *cstr) { +String::String(const char *cstr) { init(); if(cstr) copy(cstr, strlen(cstr)); } -ICACHE_FLASH_ATTR String::String(const String &value) { +String::String(const String &value) { init(); *this = value; } -ICACHE_FLASH_ATTR String::String(const __FlashStringHelper *pstr) { +String::String(const __FlashStringHelper *pstr) { init(); *this = pstr; // see operator = } #ifdef __GXX_EXPERIMENTAL_CXX0X__ -ICACHE_FLASH_ATTR String::String(String &&rval) { +String::String(String &&rval) { init(); move(rval); } -ICACHE_FLASH_ATTR String::String(StringSumHelper &&rval) { +String::String(StringSumHelper &&rval) { init(); move(rval); } #endif -ICACHE_FLASH_ATTR String::String(char c) { +String::String(char c) { init(); char buf[2]; buf[0] = c; @@ -70,54 +65,54 @@ ICACHE_FLASH_ATTR String::String(char c) { *this = buf; } -ICACHE_FLASH_ATTR String::String(unsigned char value, unsigned char base) { +String::String(unsigned char value, unsigned char base) { init(); char buf[1 + 8 * sizeof(unsigned char)]; utoa(value, buf, base); *this = buf; } -ICACHE_FLASH_ATTR String::String(int value, unsigned char base) { +String::String(int value, unsigned char base) { init(); char buf[2 + 8 * sizeof(int)]; itoa(value, buf, base); *this = buf; } -ICACHE_FLASH_ATTR String::String(unsigned int value, unsigned char base) { +String::String(unsigned int value, unsigned char base) { init(); char buf[1 + 8 * sizeof(unsigned int)]; utoa(value, buf, base); *this = buf; } -ICACHE_FLASH_ATTR String::String(long value, unsigned char base) { +String::String(long value, unsigned char base) { init(); char buf[2 + 8 * sizeof(long)]; ltoa(value, buf, base); *this = buf; } -ICACHE_FLASH_ATTR String::String(unsigned long value, unsigned char base) { +String::String(unsigned long value, unsigned char base) { init(); char buf[1 + 8 * sizeof(unsigned long)]; ultoa(value, buf, base); *this = buf; } -ICACHE_FLASH_ATTR String::String(float value, unsigned char decimalPlaces) { +String::String(float value, unsigned char decimalPlaces) { init(); char buf[33]; *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); } -ICACHE_FLASH_ATTR String::String(double value, unsigned char decimalPlaces) { +String::String(double value, unsigned char decimalPlaces) { init(); char buf[33]; *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); } -ICACHE_FLASH_ATTR String::~String() { +String::~String() { if(buffer) { free(buffer); } @@ -134,13 +129,13 @@ inline void String::init(void) { len = 0; } -void ICACHE_FLASH_ATTR String::invalidate(void) { +void String::invalidate(void) { if(buffer) free(buffer); init(); } -unsigned char ICACHE_FLASH_ATTR String::reserve(unsigned int size) { +unsigned char String::reserve(unsigned int size) { if(buffer && capacity >= size) return 1; if(changeBuffer(size)) { @@ -151,7 +146,7 @@ unsigned char ICACHE_FLASH_ATTR String::reserve(unsigned int size) { return 0; } -unsigned char ICACHE_FLASH_ATTR String::changeBuffer(unsigned int maxStrLen) { +unsigned char String::changeBuffer(unsigned int maxStrLen) { size_t newSize = (maxStrLen + 16) & (~0xf); char *newbuffer = (char *) realloc(buffer, newSize); if(newbuffer) { @@ -172,7 +167,7 @@ unsigned char ICACHE_FLASH_ATTR String::changeBuffer(unsigned int maxStrLen) { // /* Copy and Move */ // /*********************************************/ -String & ICACHE_FLASH_ATTR String::copy(const char *cstr, unsigned int length) { +String & String::copy(const char *cstr, unsigned int length) { if(!reserve(length)) { invalidate(); return *this; @@ -182,7 +177,7 @@ String & ICACHE_FLASH_ATTR String::copy(const char *cstr, unsigned int length) { return *this; } -String & ICACHE_FLASH_ATTR String::copy(const __FlashStringHelper *pstr, unsigned int length) { +String & String::copy(const __FlashStringHelper *pstr, unsigned int length) { if (!reserve(length)) { invalidate(); return *this; @@ -193,7 +188,7 @@ String & ICACHE_FLASH_ATTR String::copy(const __FlashStringHelper *pstr, unsigne } #ifdef __GXX_EXPERIMENTAL_CXX0X__ -void ICACHE_FLASH_ATTR String::move(String &rhs) { +void String::move(String &rhs) { if(buffer) { if(capacity >= rhs.len) { strcpy(buffer, rhs.buffer); @@ -213,7 +208,7 @@ void ICACHE_FLASH_ATTR String::move(String &rhs) { } #endif -String & ICACHE_FLASH_ATTR String::operator =(const String &rhs) { +String & String::operator =(const String &rhs) { if(this == &rhs) return *this; @@ -226,20 +221,20 @@ String & ICACHE_FLASH_ATTR String::operator =(const String &rhs) { } #ifdef __GXX_EXPERIMENTAL_CXX0X__ -String & ICACHE_FLASH_ATTR String::operator =(String &&rval) { +String & String::operator =(String &&rval) { if(this != &rval) move(rval); return *this; } -String & ICACHE_FLASH_ATTR String::operator =(StringSumHelper &&rval) { +String & String::operator =(StringSumHelper &&rval) { if(this != &rval) move(rval); return *this; } #endif -String & ICACHE_FLASH_ATTR String::operator =(const char *cstr) { +String & String::operator =(const char *cstr) { if(cstr) copy(cstr, strlen(cstr)); else @@ -248,7 +243,7 @@ String & ICACHE_FLASH_ATTR String::operator =(const char *cstr) { return *this; } -String & ICACHE_FLASH_ATTR String::operator = (const __FlashStringHelper *pstr) +String & String::operator = (const __FlashStringHelper *pstr) { if (pstr) copy(pstr, strlen_P((PGM_P)pstr)); else invalidate(); @@ -260,11 +255,11 @@ String & ICACHE_FLASH_ATTR String::operator = (const __FlashStringHelper *pstr) // /* concat */ // /*********************************************/ -unsigned char ICACHE_FLASH_ATTR String::concat(const String &s) { +unsigned char String::concat(const String &s) { return concat(s.buffer, s.len); } -unsigned char ICACHE_FLASH_ATTR String::concat(const char *cstr, unsigned int length) { +unsigned char String::concat(const char *cstr, unsigned int length) { unsigned int newlen = len + length; if(!cstr) return 0; @@ -277,62 +272,62 @@ unsigned char ICACHE_FLASH_ATTR String::concat(const char *cstr, unsigned int le return 1; } -unsigned char ICACHE_FLASH_ATTR String::concat(const char *cstr) { +unsigned char String::concat(const char *cstr) { if(!cstr) return 0; return concat(cstr, strlen(cstr)); } -unsigned char ICACHE_FLASH_ATTR String::concat(char c) { +unsigned char String::concat(char c) { char buf[2]; buf[0] = c; buf[1] = 0; return concat(buf, 1); } -unsigned char ICACHE_FLASH_ATTR String::concat(unsigned char num) { +unsigned char String::concat(unsigned char num) { char buf[1 + 3 * sizeof(unsigned char)]; itoa(num, buf, 10); return concat(buf, strlen(buf)); } -unsigned char ICACHE_FLASH_ATTR String::concat(int num) { +unsigned char String::concat(int num) { char buf[2 + 3 * sizeof(int)]; itoa(num, buf, 10); return concat(buf, strlen(buf)); } -unsigned char ICACHE_FLASH_ATTR String::concat(unsigned int num) { +unsigned char String::concat(unsigned int num) { char buf[1 + 3 * sizeof(unsigned int)]; utoa(num, buf, 10); return concat(buf, strlen(buf)); } -unsigned char ICACHE_FLASH_ATTR String::concat(long num) { +unsigned char String::concat(long num) { char buf[2 + 3 * sizeof(long)]; ltoa(num, buf, 10); return concat(buf, strlen(buf)); } -unsigned char ICACHE_FLASH_ATTR String::concat(unsigned long num) { +unsigned char String::concat(unsigned long num) { char buf[1 + 3 * sizeof(unsigned long)]; ultoa(num, buf, 10); return concat(buf, strlen(buf)); } -unsigned char ICACHE_FLASH_ATTR String::concat(float num) { +unsigned char String::concat(float num) { char buf[20]; char* string = dtostrf(num, 4, 2, buf); return concat(string, strlen(string)); } -unsigned char ICACHE_FLASH_ATTR String::concat(double num) { +unsigned char String::concat(double num) { char buf[20]; char* string = dtostrf(num, 4, 2, buf); return concat(string, strlen(string)); } -unsigned char ICACHE_FLASH_ATTR String::concat(const __FlashStringHelper * str) { +unsigned char String::concat(const __FlashStringHelper * str) { if (!str) return 0; int length = strlen_P((PGM_P)str); if (length == 0) return 1; @@ -347,77 +342,77 @@ unsigned char ICACHE_FLASH_ATTR String::concat(const __FlashStringHelper * str) /* Concatenate */ /*********************************************/ -StringSumHelper & ICACHE_FLASH_ATTR operator +(const StringSumHelper &lhs, const String &rhs) { +StringSumHelper & operator +(const StringSumHelper &lhs, const String &rhs) { StringSumHelper &a = const_cast(lhs); if(!a.concat(rhs.buffer, rhs.len)) a.invalidate(); return a; } -StringSumHelper & ICACHE_FLASH_ATTR operator +(const StringSumHelper &lhs, const char *cstr) { +StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr) { StringSumHelper &a = const_cast(lhs); if(!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate(); return a; } -StringSumHelper & ICACHE_FLASH_ATTR operator +(const StringSumHelper &lhs, char c) { +StringSumHelper & operator +(const StringSumHelper &lhs, char c) { StringSumHelper &a = const_cast(lhs); if(!a.concat(c)) a.invalidate(); return a; } -StringSumHelper & ICACHE_FLASH_ATTR operator +(const StringSumHelper &lhs, unsigned char num) { +StringSumHelper & operator +(const StringSumHelper &lhs, unsigned char num) { StringSumHelper &a = const_cast(lhs); if(!a.concat(num)) a.invalidate(); return a; } -StringSumHelper & ICACHE_FLASH_ATTR operator +(const StringSumHelper &lhs, int num) { +StringSumHelper & operator +(const StringSumHelper &lhs, int num) { StringSumHelper &a = const_cast(lhs); if(!a.concat(num)) a.invalidate(); return a; } -StringSumHelper & ICACHE_FLASH_ATTR operator +(const StringSumHelper &lhs, unsigned int num) { +StringSumHelper & operator +(const StringSumHelper &lhs, unsigned int num) { StringSumHelper &a = const_cast(lhs); if(!a.concat(num)) a.invalidate(); return a; } -StringSumHelper & ICACHE_FLASH_ATTR operator +(const StringSumHelper &lhs, long num) { +StringSumHelper & operator +(const StringSumHelper &lhs, long num) { StringSumHelper &a = const_cast(lhs); if(!a.concat(num)) a.invalidate(); return a; } -StringSumHelper & ICACHE_FLASH_ATTR operator +(const StringSumHelper &lhs, unsigned long num) { +StringSumHelper & operator +(const StringSumHelper &lhs, unsigned long num) { StringSumHelper &a = const_cast(lhs); if(!a.concat(num)) a.invalidate(); return a; } -StringSumHelper & ICACHE_FLASH_ATTR operator +(const StringSumHelper &lhs, float num) { +StringSumHelper & operator +(const StringSumHelper &lhs, float num) { StringSumHelper &a = const_cast(lhs); if(!a.concat(num)) a.invalidate(); return a; } -StringSumHelper & ICACHE_FLASH_ATTR operator +(const StringSumHelper &lhs, double num) { +StringSumHelper & operator +(const StringSumHelper &lhs, double num) { StringSumHelper &a = const_cast(lhs); if(!a.concat(num)) a.invalidate(); return a; } -StringSumHelper & ICACHE_FLASH_ATTR operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs) +StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs) { StringSumHelper &a = const_cast(lhs); if (!a.concat(rhs)) a.invalidate(); @@ -428,7 +423,7 @@ StringSumHelper & ICACHE_FLASH_ATTR operator + (const StringSumHelper &lhs, cons // /* Comparison */ // /*********************************************/ -int ICACHE_FLASH_ATTR String::compareTo(const String &s) const { +int String::compareTo(const String &s) const { if(!buffer || !s.buffer) { if(s.buffer && s.len > 0) return 0 - *(unsigned char *) s.buffer; @@ -439,11 +434,11 @@ int ICACHE_FLASH_ATTR String::compareTo(const String &s) const { return strcmp(buffer, s.buffer); } -unsigned char ICACHE_FLASH_ATTR String::equals(const String &s2) const { +unsigned char String::equals(const String &s2) const { return (len == s2.len && compareTo(s2) == 0); } -unsigned char ICACHE_FLASH_ATTR String::equals(const char *cstr) const { +unsigned char String::equals(const char *cstr) const { if(len == 0) return (cstr == NULL || *cstr == 0); if(cstr == NULL) @@ -451,23 +446,23 @@ unsigned char ICACHE_FLASH_ATTR String::equals(const char *cstr) const { return strcmp(buffer, cstr) == 0; } -unsigned char ICACHE_FLASH_ATTR String::operator<(const String &rhs) const { +unsigned char String::operator<(const String &rhs) const { return compareTo(rhs) < 0; } -unsigned char ICACHE_FLASH_ATTR String::operator>(const String &rhs) const { +unsigned char String::operator>(const String &rhs) const { return compareTo(rhs) > 0; } -unsigned char ICACHE_FLASH_ATTR String::operator<=(const String &rhs) const { +unsigned char String::operator<=(const String &rhs) const { return compareTo(rhs) <= 0; } -unsigned char ICACHE_FLASH_ATTR String::operator>=(const String &rhs) const { +unsigned char String::operator>=(const String &rhs) const { return compareTo(rhs) >= 0; } -unsigned char ICACHE_FLASH_ATTR String::equalsIgnoreCase(const String &s2) const { +unsigned char String::equalsIgnoreCase(const String &s2) const { if(this == &s2) return 1; if(len != s2.len) @@ -483,19 +478,19 @@ unsigned char ICACHE_FLASH_ATTR String::equalsIgnoreCase(const String &s2) const return 1; } -unsigned char ICACHE_FLASH_ATTR String::startsWith(const String &s2) const { +unsigned char String::startsWith(const String &s2) const { if(len < s2.len) return 0; return startsWith(s2, 0); } -unsigned char ICACHE_FLASH_ATTR String::startsWith(const String &s2, unsigned int offset) const { +unsigned char String::startsWith(const String &s2, unsigned int offset) const { if(offset > len - s2.len || !buffer || !s2.buffer) return 0; return strncmp(&buffer[offset], s2.buffer, s2.len) == 0; } -unsigned char ICACHE_FLASH_ATTR String::endsWith(const String &s2) const { +unsigned char String::endsWith(const String &s2) const { if(len < s2.len || !buffer || !s2.buffer) return 0; return strcmp(&buffer[len - s2.len], s2.buffer) == 0; @@ -505,16 +500,16 @@ unsigned char ICACHE_FLASH_ATTR String::endsWith(const String &s2) const { // /* Character Access */ // /*********************************************/ -char ICACHE_FLASH_ATTR String::charAt(unsigned int loc) const { +char String::charAt(unsigned int loc) const { return operator[](loc); } -void ICACHE_FLASH_ATTR String::setCharAt(unsigned int loc, char c) { +void String::setCharAt(unsigned int loc, char c) { if(loc < len) buffer[loc] = c; } -char & ICACHE_FLASH_ATTR String::operator[](unsigned int index) { +char & String::operator[](unsigned int index) { static char dummy_writable_char; if(index >= len || !buffer) { dummy_writable_char = 0; @@ -523,13 +518,13 @@ char & ICACHE_FLASH_ATTR String::operator[](unsigned int index) { return buffer[index]; } -char ICACHE_FLASH_ATTR String::operator[](unsigned int index) const { +char String::operator[](unsigned int index) const { if(index >= len || !buffer) return 0; return buffer[index]; } -void ICACHE_FLASH_ATTR String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const { +void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const { if(!bufsize || !buf) return; if(index >= len) { @@ -546,13 +541,12 @@ void ICACHE_FLASH_ATTR String::getBytes(unsigned char *buf, unsigned int bufsize // /*********************************************/ // /* Search */ // /*********************************************/ -ICACHE_FLASH_ATTR ICACHE_FLASH_ATTR -int ICACHE_FLASH_ATTR String::indexOf(char c) const { +int String::indexOf(char c) const { return indexOf(c, 0); } -int ICACHE_FLASH_ATTR String::indexOf(char ch, unsigned int fromIndex) const { +int String::indexOf(char ch, unsigned int fromIndex) const { if(fromIndex >= len) return -1; const char* temp = strchr(buffer + fromIndex, ch); @@ -561,11 +555,11 @@ int ICACHE_FLASH_ATTR String::indexOf(char ch, unsigned int fromIndex) const { return temp - buffer; } -int ICACHE_FLASH_ATTR String::indexOf(const String &s2) const { +int String::indexOf(const String &s2) const { return indexOf(s2, 0); } -int ICACHE_FLASH_ATTR String::indexOf(const String &s2, unsigned int fromIndex) const { +int String::indexOf(const String &s2, unsigned int fromIndex) const { if(fromIndex >= len) return -1; const char *found = strstr(buffer + fromIndex, s2.buffer); @@ -574,11 +568,11 @@ int ICACHE_FLASH_ATTR String::indexOf(const String &s2, unsigned int fromIndex) return found - buffer; } -int ICACHE_FLASH_ATTR String::lastIndexOf(char theChar) const { +int String::lastIndexOf(char theChar) const { return lastIndexOf(theChar, len - 1); } -int ICACHE_FLASH_ATTR String::lastIndexOf(char ch, unsigned int fromIndex) const { +int String::lastIndexOf(char ch, unsigned int fromIndex) const { if(fromIndex >= len) return -1; char tempchar = buffer[fromIndex + 1]; @@ -590,11 +584,11 @@ int ICACHE_FLASH_ATTR String::lastIndexOf(char ch, unsigned int fromIndex) const return temp - buffer; } -int ICACHE_FLASH_ATTR String::lastIndexOf(const String &s2) const { +int String::lastIndexOf(const String &s2) const { return lastIndexOf(s2, len - s2.len); } -int ICACHE_FLASH_ATTR String::lastIndexOf(const String &s2, unsigned int fromIndex) const { +int String::lastIndexOf(const String &s2, unsigned int fromIndex) const { if(s2.len == 0 || len == 0 || s2.len > len) return -1; if(fromIndex >= len) @@ -610,7 +604,7 @@ int ICACHE_FLASH_ATTR String::lastIndexOf(const String &s2, unsigned int fromInd return found; } -String ICACHE_FLASH_ATTR String::substring(unsigned int left, unsigned int right) const { +String String::substring(unsigned int left, unsigned int right) const { if(left > right) { unsigned int temp = right; right = left; @@ -632,7 +626,7 @@ String ICACHE_FLASH_ATTR String::substring(unsigned int left, unsigned int right // /* Modification */ // /*********************************************/ -void ICACHE_FLASH_ATTR String::replace(char find, char replace) { +void String::replace(char find, char replace) { if(!buffer) return; for(char *p = buffer; *p; p++) { @@ -641,7 +635,7 @@ void ICACHE_FLASH_ATTR String::replace(char find, char replace) { } } -void ICACHE_FLASH_ATTR String::replace(const String& find, const String& replace) { +void String::replace(const String& find, const String& replace) { if(len == 0 || find.len == 0) return; int diff = replace.len - find.len; @@ -686,14 +680,14 @@ void ICACHE_FLASH_ATTR String::replace(const String& find, const String& replace } } -void ICACHE_FLASH_ATTR String::remove(unsigned int index) { +void String::remove(unsigned int index) { // Pass the biggest integer as the count. The remove method // below will take care of truncating it at the end of the // string. remove(index, (unsigned int) -1); } -void ICACHE_FLASH_ATTR String::remove(unsigned int index, unsigned int count) { +void String::remove(unsigned int index, unsigned int count) { if(index >= len) { return; } @@ -709,7 +703,7 @@ void ICACHE_FLASH_ATTR String::remove(unsigned int index, unsigned int count) { buffer[len] = 0; } -void ICACHE_FLASH_ATTR String::toLowerCase(void) { +void String::toLowerCase(void) { if(!buffer) return; for(char *p = buffer; *p; p++) { @@ -717,7 +711,7 @@ void ICACHE_FLASH_ATTR String::toLowerCase(void) { } } -void ICACHE_FLASH_ATTR String::toUpperCase(void) { +void String::toUpperCase(void) { if(!buffer) return; for(char *p = buffer; *p; p++) { @@ -725,7 +719,7 @@ void ICACHE_FLASH_ATTR String::toUpperCase(void) { } } -void ICACHE_FLASH_ATTR String::trim(void) { +void String::trim(void) { if(!buffer || len == 0) return; char *begin = buffer; @@ -744,13 +738,13 @@ void ICACHE_FLASH_ATTR String::trim(void) { // /* Parsing / Conversion */ // /*********************************************/ -long ICACHE_FLASH_ATTR String::toInt(void) const { +long String::toInt(void) const { if(buffer) return atol(buffer); return 0; } -float ICACHE_FLASH_ATTR String::toFloat(void) const { +float String::toFloat(void) const { if(buffer) return atof(buffer); return 0; diff --git a/cores/esp8266/core_esp8266_noniso.c b/cores/esp8266/core_esp8266_noniso.c index d5b9d82f2..c45abd2d9 100644 --- a/cores/esp8266/core_esp8266_noniso.c +++ b/cores/esp8266/core_esp8266_noniso.c @@ -1,9 +1,9 @@ -/* +/* core_esp8266_noniso.c - nonstandard (but usefull) conversion functions Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. This file is part of the esp8266 core for Arduino environment. - + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either @@ -24,10 +24,11 @@ #include #include +#include +#include +#include #include "stdlib_noniso.h" -#include "ets_sys.h" -#define sprintf ets_sprintf int atoi(const char* s) { return (int) atol(s); @@ -149,7 +150,7 @@ char* ultoa(unsigned long value, char* result, int base) { char * dtostrf(double number, signed char width, unsigned char prec, char *s) { bool negative = false; - + if (isnan(number)) { strcpy(s, "nan"); return s; @@ -160,12 +161,12 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { } char* out = s; - + int fillme = width; // how many cells to fill for the integer part if (prec > 0) { fillme -= (prec+1); - } - + } + // Handle negative numbers if (number < 0.0) { negative = true; @@ -177,40 +178,40 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { // I optimized out most of the divisions double rounding = 2.0; for (uint8_t i = 0; i < prec; ++i) - rounding *= 10.0; - rounding = 1.0 / rounding; + rounding *= 10.0; + rounding = 1.0 / rounding; number += rounding; - + // Figure out how big our number really is double tenpow = 1.0; int digitcount = 1; while (number >= 10.0 * tenpow) { - tenpow *= 10.0; + tenpow *= 10.0; digitcount++; } - + number /= tenpow; fillme -= digitcount; - + // Pad unused cells with spaces while (fillme-- > 0) { *out++ = ' '; } - + // Handle negative sign if (negative) *out++ = '-'; - + // Print the digits, and if necessary, the decimal point digitcount += prec; int8_t digit = 0; - while (digitcount-- > 0) { + while (digitcount-- > 0) { digit = (int8_t)number; if (digit > 9) digit = 9; // insurance *out++ = (char)('0' | digit); if ((digitcount == prec) && (prec > 0)) { *out++ = '.'; - } + } number -= digit; number *= 10.0; } @@ -219,5 +220,3 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { *out = 0; return s; } - - diff --git a/cores/esp8266/spiffs/spiffs_config.h b/cores/esp8266/spiffs/spiffs_config.h index 2d83c261d..2fe03b1fd 100644 --- a/cores/esp8266/spiffs/spiffs_config.h +++ b/cores/esp8266/spiffs/spiffs_config.h @@ -11,12 +11,10 @@ #include #include #include -#include "c_types.h" -#include "ets_sys.h" - +#include #define c_memcpy memcpy -#define c_printf ets_printf +#define c_printf printf #define c_memset memset typedef int16_t file_t; diff --git a/cores/esp8266/spiffs_api.cpp b/cores/esp8266/spiffs_api.cpp index 84a2a7938..5420174a9 100644 --- a/cores/esp8266/spiffs_api.cpp +++ b/cores/esp8266/spiffs_api.cpp @@ -21,406 +21,12 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "FS.h" -#undef max -#undef min -#include "FSImpl.h" -#include "spiffs/spiffs.h" -#include "debug.h" -#include - -extern "C" { -#include "c_types.h" -#include "spi_flash.h" -} +#include "spiffs_api.h" using namespace fs; -extern int32_t spiffs_hal_write(uint32_t addr, uint32_t size, uint8_t *src); -extern int32_t spiffs_hal_erase(uint32_t addr, uint32_t size); -extern int32_t spiffs_hal_read(uint32_t addr, uint32_t size, uint8_t *dst); - -static int getSpiffsMode(OpenMode openMode, AccessMode accessMode); -static bool isSpiffsFilenameValid(const char* name); - -class SPIFFSFileImpl; -class SPIFFSDirImpl; - - -class SPIFFSImpl : public FSImpl { -public: - SPIFFSImpl(uint32_t start, uint32_t size, uint32_t pageSize, uint32_t blockSize, uint32_t maxOpenFds) - : _fs({0}) - , _start(start) - , _size(size) - , _pageSize(pageSize) - , _blockSize(blockSize) - , _maxOpenFds(maxOpenFds) - { - } - - FileImplPtr open(const char* path, OpenMode openMode, AccessMode accessMode) override; - bool exists(const char* path) override; - DirImplPtr openDir(const char* path) override; - - bool rename(const char* pathFrom, const char* pathTo) override { - if (!isSpiffsFilenameValid(pathFrom)) { - DEBUGV("SPIFFSImpl::rename: invalid pathFrom=`%s`\r\n", pathFrom); - return false; - } - if (!isSpiffsFilenameValid(pathTo)) { - DEBUGV("SPIFFSImpl::rename: invalid pathTo=`%s` \r\n", pathTo); - return false; - } - auto rc = SPIFFS_rename(&_fs, pathFrom, pathTo); - if (rc != SPIFFS_OK) { - DEBUGV("SPIFFS_rename: rc=%d, from=`%s`, to=`%s`\r\n", rc, - pathFrom, pathTo); - return false; - } - return true; - } - bool info(FSInfo& info) override { - info.maxOpenFiles = _maxOpenFds; - info.blockSize = _blockSize; - info.pageSize = _pageSize; - info.maxOpenFiles = _maxOpenFds; - info.maxPathLength = SPIFFS_OBJ_NAME_LEN; - auto rc = SPIFFS_info(&_fs, &info.totalBytes, &info.usedBytes); - if (rc != SPIFFS_OK) { - DEBUGV("SPIFFS_info: rc=%d, err=%d\r\n", rc, _fs.err_code); - return false; - } - return true; - } - - bool remove(const char* path) override { - if (!isSpiffsFilenameValid(path)) { - DEBUGV("SPIFFSImpl::remove: invalid path=`%s`\r\n", path); - return false; - } - auto rc = SPIFFS_remove(&_fs, path); - if (rc != SPIFFS_OK) { - DEBUGV("SPIFFS_remove: rc=%d path=`%s`\r\n", rc, path); - return false; - } - return true; - } - - bool begin() override { - if (SPIFFS_mounted(&_fs) != 0) { - return true; - } - if (_size == 0) { - DEBUGV("SPIFFS size is zero"); - return false; - } - if (_tryMount()) { - return true; - } - auto rc = SPIFFS_format(&_fs); - if (rc != SPIFFS_OK) { - DEBUGV("SPIFFS_format: rc=%d, err=%d\r\n", rc, _fs.err_code); - return false; - } - return _tryMount(); - } - - bool format() override { - if (_size == 0) { - DEBUGV("SPIFFS size is zero"); - return false; - } - - bool wasMounted = (SPIFFS_mounted(&_fs) != 0); - - if (_tryMount()) { - SPIFFS_unmount(&_fs); - } - auto rc = SPIFFS_format(&_fs); - if (rc != SPIFFS_OK) { - DEBUGV("SPIFFS_format: rc=%d, err=%d\r\n", rc, _fs.err_code); - return false; - } - - if (wasMounted) { - return _tryMount(); - } - - return true; - } - -protected: - friend class SPIFFSFileImpl; - friend class SPIFFSDirImpl; - - spiffs* getFs() { - return &_fs; - } - - bool _tryMount() { - spiffs_config config = {0}; - - config.hal_read_f = &spiffs_hal_read; - config.hal_write_f = &spiffs_hal_write; - config.hal_erase_f = &spiffs_hal_erase; - config.phys_size = _size; - config.phys_addr = _start; - config.phys_erase_block = SPI_FLASH_SEC_SIZE; - config.log_block_size = _blockSize; - config.log_page_size = _pageSize; - - - if (((uint32_t) std::numeric_limits::max()) < (_size / _blockSize)) { - DEBUGV("spiffs_block_ix type too small"); - abort(); - } - - if (((uint32_t) std::numeric_limits::max()) < (_size / _pageSize)) { - DEBUGV("spiffs_page_ix type too small"); - abort(); - } - - if (((uint32_t) std::numeric_limits::max()) < (2 + (_size / (2*_pageSize))*2)) { - DEBUGV("spiffs_obj_id type too small"); - abort(); - } - - if (((uint32_t) std::numeric_limits::max()) < (_size / _pageSize - 1)) { - DEBUGV("spiffs_span_ix type too small"); - abort(); - } - - // hack: even though fs is not initialized at this point, - // SPIFFS_buffer_bytes_for_cache uses only fs->config.log_page_size - // suggestion: change SPIFFS_buffer_bytes_for_cache to take - // spiffs_config* instead of spiffs* as an argument - _fs.cfg.log_page_size = config.log_page_size; - - size_t workBufSize = 2 * _pageSize; - size_t fdsBufSize = SPIFFS_buffer_bytes_for_filedescs(&_fs, _maxOpenFds); - size_t cacheBufSize = SPIFFS_buffer_bytes_for_cache(&_fs, _maxOpenFds); - - if (!_workBuf) { - DEBUGV("SPIFFSImpl: allocating %d+%d+%d=%d bytes\r\n", - workBufSize, fdsBufSize, cacheBufSize, - workBufSize + fdsBufSize + cacheBufSize); - _workBuf.reset(new uint8_t[workBufSize]); - _fdsBuf.reset(new uint8_t[fdsBufSize]); - _cacheBuf.reset(new uint8_t[cacheBufSize]); - } - - DEBUGV("SPIFFSImpl: mounting fs @%x, size=%x, block=%x, page=%x\r\n", - _start, _size, _blockSize, _pageSize); - - auto err = SPIFFS_mount(&_fs, &config, _workBuf.get(), - _fdsBuf.get(), fdsBufSize, _cacheBuf.get(), cacheBufSize, - &SPIFFSImpl::_check_cb); - - DEBUGV("SPIFFSImpl: mount rc=%d\r\n", err); - - return err == SPIFFS_OK; - } - - static void _check_cb(spiffs_check_type type, spiffs_check_report report, - uint32_t arg1, uint32_t arg2) { - // TODO: spiffs doesn't pass any context pointer along with _check_cb, - // so we can't do anything useful here other than perhaps - // feeding the watchdog - } - - spiffs _fs; - - uint32_t _start; - uint32_t _size; - uint32_t _pageSize; - uint32_t _blockSize; - uint32_t _maxOpenFds; - - std::unique_ptr _workBuf; - std::unique_ptr _fdsBuf; - std::unique_ptr _cacheBuf; -}; - -#define CHECKFD() while (_fd == 0) { panic(); } - -class SPIFFSFileImpl : public FileImpl { -public: - SPIFFSFileImpl(SPIFFSImpl* fs, spiffs_file fd) - : _fs(fs) - , _fd(fd) - , _stat({0}) - , _written(false) - { - _getStat(); - } - - ~SPIFFSFileImpl() override { - close(); - } - - size_t write(const uint8_t *buf, size_t size) override { - CHECKFD(); - - auto result = SPIFFS_write(_fs->getFs(), _fd, (void*) buf, size); - if (result < 0) { - DEBUGV("SPIFFS_write rc=%d\r\n", result); - return 0; - } - _written = true; - return result; - } - - size_t read(uint8_t* buf, size_t size) override { - CHECKFD(); - auto result = SPIFFS_read(_fs->getFs(), _fd, (void*) buf, size); - if (result < 0) { - DEBUGV("SPIFFS_read rc=%d\r\n", result); - return 0; - } - - return result; - } - - void flush() override { - CHECKFD(); - - auto rc = SPIFFS_fflush(_fs->getFs(), _fd); - if (rc < 0) { - DEBUGV("SPIFFS_fflush rc=%d\r\n", rc); - } - _written = true; - } - - bool seek(uint32_t pos, SeekMode mode) override { - CHECKFD(); - - int32_t offset = static_cast(pos); - if (mode == SeekEnd) { - offset = -offset; - } - auto rc = SPIFFS_lseek(_fs->getFs(), _fd, pos, (int) mode); - if (rc < 0) { - DEBUGV("SPIFFS_lseek rc=%d\r\n", rc); - return false; - } - - return true; - } - - size_t position() const override { - CHECKFD(); - - auto result = SPIFFS_lseek(_fs->getFs(), _fd, 0, SPIFFS_SEEK_CUR); - if (result < 0) { - DEBUGV("SPIFFS_tell rc=%d\r\n", result); - return 0; - } - - return result; - } - - size_t size() const override { - CHECKFD(); - if (_written) { - _getStat(); - } - return _stat.size; - } - - void close() override { - CHECKFD(); - - SPIFFS_close(_fs->getFs(), _fd); - DEBUGV("SPIFFS_close: fd=%d\r\n", _fd); - } - - const char* name() const override { - CHECKFD(); - - return (const char*) _stat.name; - } - -protected: - void _getStat() const{ - CHECKFD(); - auto rc = SPIFFS_fstat(_fs->getFs(), _fd, &_stat); - if (rc != SPIFFS_OK) { - DEBUGV("SPIFFS_fstat rc=%d\r\n", rc); - _stat = {0}; - } - _written = false; - } - - SPIFFSImpl* _fs; - spiffs_file _fd; - mutable spiffs_stat _stat; - mutable bool _written; -}; - -class SPIFFSDirImpl : public DirImpl { -public: - SPIFFSDirImpl(const String& pattern, SPIFFSImpl* fs, spiffs_DIR& dir) - : _pattern(pattern) - , _fs(fs) - , _dir(dir) - , _valid(false) - { - } - - ~SPIFFSDirImpl() override { - SPIFFS_closedir(&_dir); - } - - FileImplPtr openFile(OpenMode openMode, AccessMode accessMode) override { - if (!_valid) { - return FileImplPtr(); - } - int mode = getSpiffsMode(openMode, accessMode); - auto fs = _fs->getFs(); - spiffs_file fd = SPIFFS_open_by_dirent(fs, &_dirent, mode, 0); - if (fd < 0) { - DEBUGV("SPIFFSDirImpl::openFile: fd=%d path=`%s` openMode=%d accessMode=%d err=%d\r\n", - fd, _dirent.name, openMode, accessMode, fs->err_code); - return FileImplPtr(); - } - return std::make_shared(_fs, fd); - } - - const char* fileName() override { - if (!_valid) - return nullptr; - - return (const char*) _dirent.name; - } - - size_t fileSize() override { - if (!_valid) - return 0; - - return _dirent.size; - } - - bool next() override { - const int n = _pattern.length(); - do { - spiffs_dirent* result = SPIFFS_readdir(&_dir, &_dirent); - _valid = (result != nullptr); - } while(_valid && strncmp((const char*) _dirent.name, _pattern.c_str(), n) != 0); - return _valid; - } - -protected: - String _pattern; - SPIFFSImpl* _fs; - spiffs_DIR _dir; - spiffs_dirent _dirent; - bool _valid; -}; - - -FileImplPtr SPIFFSImpl::open(const char* path, OpenMode openMode, AccessMode accessMode) { +FileImplPtr SPIFFSImpl::open(const char* path, OpenMode openMode, AccessMode accessMode) +{ if (!isSpiffsFilenameValid(path)) { DEBUGV("SPIFFSImpl::open: invalid path=`%s` \r\n", path); return FileImplPtr(); @@ -429,24 +35,25 @@ FileImplPtr SPIFFSImpl::open(const char* path, OpenMode openMode, AccessMode acc int fd = SPIFFS_open(&_fs, path, mode, 0); if (fd < 0 && _fs.err_code == SPIFFS_ERR_DELETED && (openMode & OM_CREATE)) { DEBUGV("SPIFFSImpl::open: fd=%d path=`%s` openMode=%d accessMode=%d err=%d, trying to remove\r\n", - fd, path, openMode, accessMode, _fs.err_code); + fd, path, openMode, accessMode, _fs.err_code); auto rc = SPIFFS_remove(&_fs, path); if (rc != SPIFFS_OK) { DEBUGV("SPIFFSImpl::open: SPIFFS_ERR_DELETED, but failed to remove path=`%s` openMode=%d accessMode=%d err=%d\r\n", - path, openMode, accessMode, _fs.err_code); + path, openMode, accessMode, _fs.err_code); return FileImplPtr(); } fd = SPIFFS_open(&_fs, path, mode, 0); } if (fd < 0) { DEBUGV("SPIFFSImpl::open: fd=%d path=`%s` openMode=%d accessMode=%d err=%d\r\n", - fd, path, openMode, accessMode, _fs.err_code); + fd, path, openMode, accessMode, _fs.err_code); return FileImplPtr(); } return std::make_shared(this, fd); } -bool SPIFFSImpl::exists(const char* path) { +bool SPIFFSImpl::exists(const char* path) +{ if (!isSpiffsFilenameValid(path)) { DEBUGV("SPIFFSImpl::exists: invalid path=`%s` \r\n", path); return false; @@ -456,7 +63,8 @@ bool SPIFFSImpl::exists(const char* path) { return rc == SPIFFS_OK; } -DirImplPtr SPIFFSImpl::openDir(const char* path) { +DirImplPtr SPIFFSImpl::openDir(const char* path) +{ if (!isSpiffsFilenameValid(path)) { DEBUGV("SPIFFSImpl::openDir: invalid path=`%s` \r\n", path); return DirImplPtr(); @@ -470,7 +78,8 @@ DirImplPtr SPIFFSImpl::openDir(const char* path) { return std::make_shared(path, this, dir); } -static int getSpiffsMode(OpenMode openMode, AccessMode accessMode) { +int getSpiffsMode(OpenMode openMode, AccessMode accessMode) +{ int mode = 0; if (openMode & OM_CREATE) { mode |= SPIFFS_CREAT; @@ -490,24 +99,32 @@ static int getSpiffsMode(OpenMode openMode, AccessMode accessMode) { return mode; } -static bool isSpiffsFilenameValid(const char* name) { - if (name == nullptr) +bool isSpiffsFilenameValid(const char* name) +{ + if (name == nullptr) { return false; + } auto len = strlen(name); return len > 0 && len < SPIFFS_OBJ_NAME_LEN; } // these symbols should be defined in the linker script for each flash layout +#ifdef ARDUINO extern "C" uint32_t _SPIFFS_start; extern "C" uint32_t _SPIFFS_end; extern "C" uint32_t _SPIFFS_page; extern "C" uint32_t _SPIFFS_block; -static SPIFFSImpl s_defaultFs( - (uint32_t) (&_SPIFFS_start) - 0x40200000, - (uint32_t) (&_SPIFFS_end) - (uint32_t) (&_SPIFFS_start), - (uint32_t) &_SPIFFS_page, - (uint32_t) &_SPIFFS_block, - 5); +#define SPIFFS_PHYS_ADDR ((uint32_t) (&_SPIFFS_start) - 0x40200000) +#define SPIFFS_PHYS_SIZE ((uint32_t) (&_SPIFFS_end) - (uint32_t) (&_SPIFFS_start)) +#define SPIFFS_PHYS_PAGE ((uint32_t) &_SPIFFS_page) +#define SPIFFS_PHYS_BLOCK ((uint32_t) &_SPIFFS_block) -FS SPIFFS = FS(FSImplPtr(&s_defaultFs)); +FS SPIFFS = FS(FSImplPtr(new SPIFFSImpl( + SPIFFS_PHYS_ADDR, + SPIFFS_PHYS_SIZE, + SPIFFS_PHYS_PAGE, + SPIFFS_PHYS_BLOCK, + 5))); + +#endif diff --git a/cores/esp8266/spiffs_api.h b/cores/esp8266/spiffs_api.h new file mode 100644 index 000000000..cf157da79 --- /dev/null +++ b/cores/esp8266/spiffs_api.h @@ -0,0 +1,451 @@ +#ifndef spiffs_api_h +#define spiffs_api_h + +/* + spiffs_api.h - file system wrapper for SPIFFS + Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. + + This code was influenced by NodeMCU and Sming libraries, and first version of + Arduino wrapper written by Hristo Gochkov. + + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include "FS.h" +#undef max +#undef min +#include "FSImpl.h" +#include "spiffs/spiffs.h" +#include "debug.h" +#include "flash_utils.h" + +using namespace fs; + +extern int32_t spiffs_hal_write(uint32_t addr, uint32_t size, uint8_t *src); +extern int32_t spiffs_hal_erase(uint32_t addr, uint32_t size); +extern int32_t spiffs_hal_read(uint32_t addr, uint32_t size, uint8_t *dst); + +int getSpiffsMode(OpenMode openMode, AccessMode accessMode); +bool isSpiffsFilenameValid(const char* name); + +class SPIFFSFileImpl; +class SPIFFSDirImpl; + +class SPIFFSImpl : public FSImpl +{ +public: + SPIFFSImpl(uint32_t start, uint32_t size, uint32_t pageSize, uint32_t blockSize, uint32_t maxOpenFds) + : _fs({0}) + , _start(start) + , _size(size) + , _pageSize(pageSize) + , _blockSize(blockSize) + , _maxOpenFds(maxOpenFds) + { + } + + FileImplPtr open(const char* path, OpenMode openMode, AccessMode accessMode) override; + bool exists(const char* path) override; + DirImplPtr openDir(const char* path) override; + + bool rename(const char* pathFrom, const char* pathTo) override + { + if (!isSpiffsFilenameValid(pathFrom)) { + DEBUGV("SPIFFSImpl::rename: invalid pathFrom=`%s`\r\n", pathFrom); + return false; + } + if (!isSpiffsFilenameValid(pathTo)) { + DEBUGV("SPIFFSImpl::rename: invalid pathTo=`%s` \r\n", pathTo); + return false; + } + auto rc = SPIFFS_rename(&_fs, pathFrom, pathTo); + if (rc != SPIFFS_OK) { + DEBUGV("SPIFFS_rename: rc=%d, from=`%s`, to=`%s`\r\n", rc, + pathFrom, pathTo); + return false; + } + return true; + } + bool info(FSInfo& info) override + { + info.maxOpenFiles = _maxOpenFds; + info.blockSize = _blockSize; + info.pageSize = _pageSize; + info.maxOpenFiles = _maxOpenFds; + info.maxPathLength = SPIFFS_OBJ_NAME_LEN; + uint32_t totalBytes, usedBytes; + auto rc = SPIFFS_info(&_fs, &totalBytes, &usedBytes); + if (rc != SPIFFS_OK) { + DEBUGV("SPIFFS_info: rc=%d, err=%d\r\n", rc, _fs.err_code); + return false; + } + info.totalBytes = totalBytes; + info.usedBytes = usedBytes; + return true; + } + + bool remove(const char* path) override + { + if (!isSpiffsFilenameValid(path)) { + DEBUGV("SPIFFSImpl::remove: invalid path=`%s`\r\n", path); + return false; + } + auto rc = SPIFFS_remove(&_fs, path); + if (rc != SPIFFS_OK) { + DEBUGV("SPIFFS_remove: rc=%d path=`%s`\r\n", rc, path); + return false; + } + return true; + } + + bool begin() override + { + if (SPIFFS_mounted(&_fs) != 0) { + return true; + } + if (_size == 0) { + DEBUGV("SPIFFS size is zero"); + return false; + } + if (_tryMount()) { + return true; + } + auto rc = SPIFFS_format(&_fs); + if (rc != SPIFFS_OK) { + DEBUGV("SPIFFS_format: rc=%d, err=%d\r\n", rc, _fs.err_code); + return false; + } + return _tryMount(); + } + + bool format() override + { + if (_size == 0) { + DEBUGV("SPIFFS size is zero"); + return false; + } + + bool wasMounted = (SPIFFS_mounted(&_fs) != 0); + + if (_tryMount()) { + SPIFFS_unmount(&_fs); + } + auto rc = SPIFFS_format(&_fs); + if (rc != SPIFFS_OK) { + DEBUGV("SPIFFS_format: rc=%d, err=%d\r\n", rc, _fs.err_code); + return false; + } + + if (wasMounted) { + return _tryMount(); + } + + return true; + } + +protected: + friend class SPIFFSFileImpl; + friend class SPIFFSDirImpl; + + spiffs* getFs() + { + return &_fs; + } + + bool _tryMount() + { + spiffs_config config = {0}; + + config.hal_read_f = &spiffs_hal_read; + config.hal_write_f = &spiffs_hal_write; + config.hal_erase_f = &spiffs_hal_erase; + config.phys_size = _size; + config.phys_addr = _start; + config.phys_erase_block = FLASH_SECTOR_SIZE; + config.log_block_size = _blockSize; + config.log_page_size = _pageSize; + + + if (((uint32_t) std::numeric_limits::max()) < (_size / _blockSize)) { + DEBUGV("spiffs_block_ix type too small"); + abort(); + } + + if (((uint32_t) std::numeric_limits::max()) < (_size / _pageSize)) { + DEBUGV("spiffs_page_ix type too small"); + abort(); + } + + if (((uint32_t) std::numeric_limits::max()) < (2 + (_size / (2*_pageSize))*2)) { + DEBUGV("spiffs_obj_id type too small"); + abort(); + } + + if (((uint32_t) std::numeric_limits::max()) < (_size / _pageSize - 1)) { + DEBUGV("spiffs_span_ix type too small"); + abort(); + } + + // hack: even though fs is not initialized at this point, + // SPIFFS_buffer_bytes_for_cache uses only fs->config.log_page_size + // suggestion: change SPIFFS_buffer_bytes_for_cache to take + // spiffs_config* instead of spiffs* as an argument + _fs.cfg.log_page_size = config.log_page_size; + + size_t workBufSize = 2 * _pageSize; + size_t fdsBufSize = SPIFFS_buffer_bytes_for_filedescs(&_fs, _maxOpenFds); + size_t cacheBufSize = SPIFFS_buffer_bytes_for_cache(&_fs, _maxOpenFds); + + if (!_workBuf) { + DEBUGV("SPIFFSImpl: allocating %d+%d+%d=%d bytes\r\n", + workBufSize, fdsBufSize, cacheBufSize, + workBufSize + fdsBufSize + cacheBufSize); + _workBuf.reset(new uint8_t[workBufSize]); + _fdsBuf.reset(new uint8_t[fdsBufSize]); + _cacheBuf.reset(new uint8_t[cacheBufSize]); + } + + DEBUGV("SPIFFSImpl: mounting fs @%x, size=%x, block=%x, page=%x\r\n", + _start, _size, _blockSize, _pageSize); + + auto err = SPIFFS_mount(&_fs, &config, _workBuf.get(), + _fdsBuf.get(), fdsBufSize, _cacheBuf.get(), cacheBufSize, + &SPIFFSImpl::_check_cb); + + DEBUGV("SPIFFSImpl: mount rc=%d\r\n", err); + + return err == SPIFFS_OK; + } + + static void _check_cb(spiffs_check_type type, spiffs_check_report report, + uint32_t arg1, uint32_t arg2) + { + // TODO: spiffs doesn't pass any context pointer along with _check_cb, + // so we can't do anything useful here other than perhaps + // feeding the watchdog + } + + spiffs _fs; + + uint32_t _start; + uint32_t _size; + uint32_t _pageSize; + uint32_t _blockSize; + uint32_t _maxOpenFds; + + std::unique_ptr _workBuf; + std::unique_ptr _fdsBuf; + std::unique_ptr _cacheBuf; +}; + +#define CHECKFD() while (_fd == 0) { panic(); } + +class SPIFFSFileImpl : public FileImpl +{ +public: + SPIFFSFileImpl(SPIFFSImpl* fs, spiffs_file fd) + : _fs(fs) + , _fd(fd) + , _stat({0}) + , _written(false) + { + _getStat(); + } + + ~SPIFFSFileImpl() override + { + close(); + } + + size_t write(const uint8_t *buf, size_t size) override + { + CHECKFD(); + + auto result = SPIFFS_write(_fs->getFs(), _fd, (void*) buf, size); + if (result < 0) { + DEBUGV("SPIFFS_write rc=%d\r\n", result); + return 0; + } + _written = true; + return result; + } + + size_t read(uint8_t* buf, size_t size) override + { + CHECKFD(); + auto result = SPIFFS_read(_fs->getFs(), _fd, (void*) buf, size); + if (result < 0) { + DEBUGV("SPIFFS_read rc=%d\r\n", result); + return 0; + } + + return result; + } + + void flush() override + { + CHECKFD(); + + auto rc = SPIFFS_fflush(_fs->getFs(), _fd); + if (rc < 0) { + DEBUGV("SPIFFS_fflush rc=%d\r\n", rc); + } + _written = true; + } + + bool seek(uint32_t pos, SeekMode mode) override + { + CHECKFD(); + + int32_t offset = static_cast(pos); + if (mode == SeekEnd) { + offset = -offset; + } + auto rc = SPIFFS_lseek(_fs->getFs(), _fd, pos, (int) mode); + if (rc < 0) { + DEBUGV("SPIFFS_lseek rc=%d\r\n", rc); + return false; + } + + return true; + } + + size_t position() const override + { + CHECKFD(); + + auto result = SPIFFS_lseek(_fs->getFs(), _fd, 0, SPIFFS_SEEK_CUR); + if (result < 0) { + DEBUGV("SPIFFS_tell rc=%d\r\n", result); + return 0; + } + + return result; + } + + size_t size() const override + { + CHECKFD(); + if (_written) { + _getStat(); + } + return _stat.size; + } + + void close() override + { + CHECKFD(); + + SPIFFS_close(_fs->getFs(), _fd); + DEBUGV("SPIFFS_close: fd=%d\r\n", _fd); + } + + const char* name() const override + { + CHECKFD(); + + return (const char*) _stat.name; + } + +protected: + void _getStat() const + { + CHECKFD(); + auto rc = SPIFFS_fstat(_fs->getFs(), _fd, &_stat); + if (rc != SPIFFS_OK) { + DEBUGV("SPIFFS_fstat rc=%d\r\n", rc); + _stat = {0}; + } + _written = false; + } + + SPIFFSImpl* _fs; + spiffs_file _fd; + mutable spiffs_stat _stat; + mutable bool _written; +}; + +class SPIFFSDirImpl : public DirImpl +{ +public: + SPIFFSDirImpl(const String& pattern, SPIFFSImpl* fs, spiffs_DIR& dir) + : _pattern(pattern) + , _fs(fs) + , _dir(dir) + , _valid(false) + { + } + + ~SPIFFSDirImpl() override + { + SPIFFS_closedir(&_dir); + } + + FileImplPtr openFile(OpenMode openMode, AccessMode accessMode) override + { + if (!_valid) { + return FileImplPtr(); + } + int mode = getSpiffsMode(openMode, accessMode); + auto fs = _fs->getFs(); + spiffs_file fd = SPIFFS_open_by_dirent(fs, &_dirent, mode, 0); + if (fd < 0) { + DEBUGV("SPIFFSDirImpl::openFile: fd=%d path=`%s` openMode=%d accessMode=%d err=%d\r\n", + fd, _dirent.name, openMode, accessMode, fs->err_code); + return FileImplPtr(); + } + return std::make_shared(_fs, fd); + } + + const char* fileName() override + { + if (!_valid) { + return nullptr; + } + + return (const char*) _dirent.name; + } + + size_t fileSize() override + { + if (!_valid) { + return 0; + } + + return _dirent.size; + } + + bool next() override + { + const int n = _pattern.length(); + do { + spiffs_dirent* result = SPIFFS_readdir(&_dir, &_dirent); + _valid = (result != nullptr); + } while(_valid && strncmp((const char*) _dirent.name, _pattern.c_str(), n) != 0); + return _valid; + } + +protected: + String _pattern; + SPIFFSImpl* _fs; + spiffs_DIR _dir; + spiffs_dirent _dirent; + bool _valid; +}; + + +#endif//spiffs_api_h