diff --git a/cores/esp8266/Arduino.h b/cores/esp8266/Arduino.h index 82cc42550..bd5f79625 100644 --- a/cores/esp8266/Arduino.h +++ b/cores/esp8266/Arduino.h @@ -214,6 +214,7 @@ void loop(void); #include "HardwareSerial.h" #include "FileSystem.h" #include "Esp.h" +#include "debug.h" uint16_t makeWord(uint16_t w); uint16_t makeWord(byte h, byte l); @@ -231,6 +232,7 @@ long random(long, long); void randomSeed(unsigned int); long map(long, long, long, long, long); + #endif #include "pins_arduino.h" diff --git a/cores/esp8266/FileSystem.cpp b/cores/esp8266/FileSystem.cpp index e33dae38b..7e42af06b 100755 --- a/cores/esp8266/FileSystem.cpp +++ b/cores/esp8266/FileSystem.cpp @@ -1,178 +1,208 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/anakod/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - ****/ +/* + FileSystem.cpp - SPIFS implementation for esp8266 + Copyright (c) 2015 Hristo Gochkov. 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 + 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 "FileSystem.h" -#include "WString.h" +#include "Arduino.h" -file_t fileOpen(const String name, FileOpenFlags flags) -{ - int repeats = 0; - bool notExist; - bool canRecreate = (flags & eFO_CreateIfNotExist) == eFO_CreateIfNotExist; - int res; - - do - { - notExist = false; - res = SPIFFS_open(&_filesystemStorageHandle, name.c_str(), (spiffs_flags)flags, 0); - int code = SPIFFS_errno(&_filesystemStorageHandle); - if (res < 0) - { - debugf("open errno %d\n", code); - notExist = (code == SPIFFS_ERR_NOT_FOUND || code == SPIFFS_ERR_DELETED || code == SPIFFS_ERR_FILE_DELETED || code == SPIFFS_ERR_IS_FREE); - //debugf("recreate? %d %d %d", notExist, canRecreate, (repeats < 3)); - if (notExist && canRecreate) - fileDelete(name); // fix for deleted files - } - } while (notExist && canRecreate && repeats++ < 3); - - return res; +boolean FSClass::mount(){ + if(_mounted) return true; + _mounted = spiffs_mount(); + return _mounted; } -void fileClose(file_t file) -{ - SPIFFS_close(&_filesystemStorageHandle, file); +void FSClass::unmount(){ + if(!_mounted) return; + spiffs_unmount(); + _mounted = false; } -size_t fileWrite(file_t file, const void* data, size_t size) -{ - int res = SPIFFS_write(&_filesystemStorageHandle, file, (void *)data, size); - if (res < 0) - { - debugf("write errno %d\n", SPIFFS_errno(&_filesystemStorageHandle)); - return res; - } - return res; +boolean FSClass::format(){ + return spiffs_format(); } -size_t fileRead(file_t file, void* data, size_t size) -{ - int res = SPIFFS_read(&_filesystemStorageHandle, file, data, size); - if (res < 0) - { - debugf("read errno %d\n", SPIFFS_errno(&_filesystemStorageHandle)); - return res; - } - return res; -} - -int fileSeek(file_t file, int offset, SeekOriginFlags origin) -{ - return SPIFFS_lseek(&_filesystemStorageHandle, file, offset, origin); -} - -bool fileIsEOF(file_t file) -{ - return SPIFFS_eof(&_filesystemStorageHandle, file); -} - -int32_t fileTell(file_t file) -{ - return SPIFFS_tell(&_filesystemStorageHandle, file); -} - -int fileFlush(file_t file) -{ - return SPIFFS_fflush(&_filesystemStorageHandle, file); -} - -int fileStats(const String name, spiffs_stat *stat) -{ - return SPIFFS_stat(&_filesystemStorageHandle, name.c_str(), stat); -} - -int fileStats(file_t file, spiffs_stat *stat) -{ - return SPIFFS_fstat(&_filesystemStorageHandle, file, stat); -} - -void fileDelete(const String name) -{ - SPIFFS_remove(&_filesystemStorageHandle, name.c_str()); -} - -void fileDelete(file_t file) -{ - SPIFFS_fremove(&_filesystemStorageHandle, file); -} - -bool fileExist(const String name) -{ +boolean FSClass::exists(const char *filename){ spiffs_stat stat = {0}; - if (fileStats(name.c_str(), &stat) < 0) return false; + if (SPIFFS_stat(&_filesystemStorageHandle, filename, &stat) < 0) return false; return stat.name[0] != '\0'; } +boolean FSClass::create(const char *filepath){ + return SPIFFS_creat(&_filesystemStorageHandle, filepath, 0) == 0; +} -int fileLastError(file_t fd) -{ +boolean FSClass::remove(const char *filepath){ + return SPIFFS_remove(&_filesystemStorageHandle, filepath) == 0; +} + +boolean FSClass::rename(const char *filename, const char *newname){ + return SPIFFS_rename(&_filesystemStorageHandle, filename, newname) == 0; +} + +FSFile FSClass::open(const char *filename, uint8_t mode){ + int repeats = 0; + bool notExist; + bool canRecreate = (mode & SPIFFS_CREAT) == SPIFFS_CREAT; + int res; + + do{ + notExist = false; + res = SPIFFS_open(&_filesystemStorageHandle, filename, (spiffs_flags)mode, 0); + int code = SPIFFS_errno(&_filesystemStorageHandle); + if (res < 0){ + debugf("open errno %d\n", code); + notExist = (code == SPIFFS_ERR_NOT_FOUND || code == SPIFFS_ERR_DELETED || code == SPIFFS_ERR_FILE_DELETED || code == SPIFFS_ERR_IS_FREE); + if (notExist && canRecreate) + remove(filename); // fix for deleted files + } + } while (notExist && canRecreate && repeats++ < 3); + + if(res){ + return FSFile(res); + } + return FSFile(); +} + +FSClass FS; + +FSFile::FSFile(){ + _file = 0; + _stats = {0}; +} + +FSFile::FSFile(file_t f){ + _file = f; + if(SPIFFS_fstat(&_filesystemStorageHandle, _file, &_stats) != 0){ + debugf("mount errno %d\n", SPIFFS_errno(&_filesystemStorageHandle)); + } +} + +void FSFile::close(){ + if (! _file) return; + SPIFFS_close(&_filesystemStorageHandle, _file); + _file = 0; +} + +uint32_t FSFile::size(){ + if(! _file) return 0; + uint32_t pos = SPIFFS_tell(&_filesystemStorageHandle, _file); + SPIFFS_lseek(&_filesystemStorageHandle, _file, 0, SPIFFS_SEEK_END); + uint32_t size = SPIFFS_tell(&_filesystemStorageHandle, _file); + SPIFFS_lseek(&_filesystemStorageHandle, _file, pos, SPIFFS_SEEK_SET); + return size; +} + +uint32_t FSFile::seek(uint32_t pos){ + if (! _file) return 0; + return SPIFFS_lseek(&_filesystemStorageHandle, _file, pos, SPIFFS_SEEK_SET); +} + +uint32_t FSFile::position(){ + if (! _file) return 0; + return SPIFFS_tell(&_filesystemStorageHandle, _file); +} + +boolean FSFile::eof(){ + if (! _file) return 0; + return SPIFFS_eof(&_filesystemStorageHandle, _file); +} + +boolean FSFile::isDirectory(void){ + return false; +} + +int FSFile::read(void *buf, uint16_t nbyte){ + if (! _file) return -1; + return SPIFFS_read(&_filesystemStorageHandle, _file, buf, nbyte); +} + +int FSFile::read(){ + if (! _file) return -1; + int val; + if(SPIFFS_read(&_filesystemStorageHandle, _file, &val, 1) != 1) return -1; + return val; +} + +int FSFile::peek() { + if (! _file) return 0; + int c = read(); + SPIFFS_lseek(&_filesystemStorageHandle, _file, -1, SPIFFS_SEEK_CUR); + return c; +} + +int FSFile::available() { + if (! _file) return 0; + uint32_t pos = SPIFFS_tell(&_filesystemStorageHandle, _file); + SPIFFS_lseek(&_filesystemStorageHandle, _file, 0, SPIFFS_SEEK_END); + uint32_t size = SPIFFS_tell(&_filesystemStorageHandle, _file); + SPIFFS_lseek(&_filesystemStorageHandle, _file, pos, SPIFFS_SEEK_SET); + return size - pos; +} + +size_t FSFile::write(const uint8_t *buf, size_t size){ + if (! _file) return 0; + return SPIFFS_write(&_filesystemStorageHandle, _file, (uint8_t *)buf, size); +} + +size_t FSFile::write(uint8_t val) { + if (! _file) return 0; + return write(&val, 1); +} + +void FSFile::flush(){ + if (! _file) return; + SPIFFS_fflush(&_filesystemStorageHandle, _file); +} + +uint32_t FSFile::remove(){ + if (! _file) return 0; + return SPIFFS_fremove(&_filesystemStorageHandle, _file); + _file = 0; +} + +int FSFile::lastError(){ return SPIFFS_errno(&_filesystemStorageHandle); } -void fileClearLastError(file_t fd) -{ +void FSFile::clearError(){ _filesystemStorageHandle.errno = SPIFFS_OK; } -void fileSetContent(const String fileName, const char *content) -{ - file_t file = fileOpen(fileName.c_str(), eFO_CreateNewAlways | eFO_WriteOnly); - fileWrite(file, content, os_strlen(content)); - fileClose(file); +char * FSFile::name(){ + return 0; } -uint32_t fileGetSize(const String fileName) -{ - file_t file = fileOpen(fileName.c_str(), eFO_ReadOnly); - // Get size - fileSeek(file, 0, eSO_FileEnd); - int size = fileTell(file); - fileClose(file); - return size; + + + + + +/* +spiffs_DIR *dirOpen(spiffs_DIR *d){ + return SPIFFS_opendir(&_filesystemStorageHandle, 0, d); } -String fileGetContent(const String fileName) -{ - file_t file = fileOpen(fileName.c_str(), eFO_ReadOnly); - // Get size - fileSeek(file, 0, eSO_FileEnd); - int size = fileTell(file); - if (size <= 0) - { - fileClose(file); - return ""; - } - fileSeek(file, 0, eSO_FileStart); - char* buffer = new char[size + 1]; - buffer[size] = 0; - fileRead(file, buffer, size); - fileClose(file); - String res = buffer; - delete[] buffer; - return res; +int dirClose(spiffs_DIR *d){ + return SPIFFS_closedir(d); } -int fileGetContent(const String fileName, char* buffer, int bufSize) -{ - if (buffer == NULL || bufSize == 0) return 0; - *buffer = 0; - - file_t file = fileOpen(fileName.c_str(), eFO_ReadOnly); - // Get size - fileSeek(file, 0, eSO_FileEnd); - int size = fileTell(file); - if (size <= 0 || bufSize <= size) - { - fileClose(file); - return 0; - } - buffer[size] = 0; - fileSeek(file, 0, eSO_FileStart); - fileRead(file, buffer, size); - fileClose(file); - return size; +file_t dirOpenFile(spiffs_dirent* entry, uint8_t flags){ + return SPIFFS_open_by_dirent(&_filesystemStorageHandle, entry, (spiffs_flags)flags, 0); } +*/ diff --git a/cores/esp8266/FileSystem.h b/cores/esp8266/FileSystem.h index c9ddb81cf..8704f260c 100755 --- a/cores/esp8266/FileSystem.h +++ b/cores/esp8266/FileSystem.h @@ -1,59 +1,105 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/anakod/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - ****/ +/* + FileSystem.h - SPIFS implementation for esp8266 -#ifndef _SMING_CORE_FILESYSTEM_H_ -#define _SMING_CORE_FILESYSTEM_H_ + Copyright (c) 2015 Hristo Gochkov. 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 + 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 +*/ +#ifndef _SPIFFS_CORE_FILESYSTEM_H_ +#define _SPIFFS_CORE_FILESYSTEM_H_ #include "spiffs/spiffs.h" +#include "Arduino.h" class String; -enum FileOpenFlags -{ - eFO_ReadOnly = SPIFFS_RDONLY, - eFO_WriteOnly = SPIFFS_WRONLY, - eFO_ReadWrite = eFO_ReadOnly | eFO_WriteOnly, - eFO_CreateIfNotExist = SPIFFS_CREAT, - eFO_Append = SPIFFS_APPEND, - eFO_Truncate = SPIFFS_TRUNC, - eFO_CreateNewAlways = eFO_CreateIfNotExist | eFO_Truncate +#define FSFILE_READ SPIFFS_RDONLY +#define FSFILE_WRITE (SPIFFS_RDONLY | SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_TRUNC) + +class FSFile : public Stream { + private: + spiffs_stat _stats; + file_t _file; + +public: + FSFile(file_t f); + FSFile(void); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + virtual int read(); + virtual int peek(); + virtual int available(); + virtual void flush(); + int read(void *buf, uint16_t nbyte); + uint32_t seek(uint32_t pos); + uint32_t remove(); + uint32_t position(); + uint32_t size(); + boolean eof(); + void close(); + int lastError(); + void clearError(); + operator bool(){ return _file > 0; } + char * name(); + boolean isDirectory(void); + + template size_t write(T &src){ + uint8_t obuf[64]; + size_t doneLen = 0; + size_t sentLen; + int i; + + while (src.available() > 64){ + src.read(obuf, 64); + sentLen = write(obuf, 64); + doneLen = doneLen + sentLen; + if(sentLen != 64){ + return doneLen; + } + } + + size_t leftLen = src.available(); + src.read(obuf, leftLen); + sentLen = write(obuf, leftLen); + doneLen = doneLen + sentLen; + return doneLen; + } + + using Print::write; }; -static FileOpenFlags operator|(FileOpenFlags lhs, FileOpenFlags rhs) -{ - return (FileOpenFlags) ((int)lhs| (int)rhs); -} +class FSClass { -typedef enum -{ - eSO_FileStart = SPIFFS_SEEK_SET, - eSO_CurrentPos = SPIFFS_SEEK_CUR, - eSO_FileEnd = SPIFFS_SEEK_END -} SeekOriginFlags; +private: + boolean _mounted; + +public: + boolean mount(); + void unmount(); + boolean format(); + boolean exists(const char *filename); + boolean create(const char *filepath); + boolean remove(const char *filepath); + boolean rename(const char *filename, const char *newname); + + FSFile open(const char *filename, uint8_t mode = FSFILE_READ); -file_t fileOpen(const String name, FileOpenFlags flags); -void fileClose(file_t file); -size_t fileWrite(file_t file, const void* data, size_t size); -size_t fileRead(file_t file, void* data, size_t size); -int fileSeek(file_t file, int offset, SeekOriginFlags origin); -bool fileIsEOF(file_t file); -int32_t fileTell(file_t file); -int fileFlush(file_t file); -int fileLastError(file_t fd); -void fileClearLastError(file_t fd); -void fileSetContent(const String fileName, const char *content); -uint32_t fileGetSize(const String fileName); -String fileGetContent(const String fileName); -int fileGetContent(const String fileName, char* buffer, int bufSize); +private: + friend class FSFile; +}; +extern FSClass FS; -int fileStats(const String name, spiffs_stat *stat); -int fileStats(file_t file, spiffs_stat *stat); -void fileDelete(const String name); -void fileDelete(file_t file); -bool fileExist(const String name); - -#endif /* _SMING_CORE_FILESYSTEM_H_ */ +#endif diff --git a/cores/esp8266/Print.cpp b/cores/esp8266/Print.cpp index 6d3687dee..c1405c9f7 100644 --- a/cores/esp8266/Print.cpp +++ b/cores/esp8266/Print.cpp @@ -18,6 +18,7 @@ Modified 23 November 2006 by David A. Mellis Modified December 2014 by Ivan Grokhotkov + Modified May 2015 by Michael C. Miller - esp8266 progmem support */ #include @@ -42,6 +43,18 @@ size_t ICACHE_FLASH_ATTR Print::write(const uint8_t *buffer, size_t size) { return n; } +size_t ICACHE_FLASH_ATTR Print::print(const __FlashStringHelper *ifsh) { + PGM_P p = reinterpret_cast(ifsh); + + size_t n = 0; + while (1) { + uint8_t c = pgm_read_byte(p++); + if (c == 0) break; + n += write(c); + } + return n; +} + size_t ICACHE_FLASH_ATTR Print::print(const String &s) { return write(s.c_str(), s.length()); } @@ -92,6 +105,12 @@ size_t ICACHE_FLASH_ATTR Print::print(double n, int digits) { return printFloat(n, digits); } +size_t ICACHE_FLASH_ATTR Print::println(const __FlashStringHelper *ifsh) { + size_t n = print(ifsh); + n += println(); + return n; +} + size_t ICACHE_FLASH_ATTR Print::print(const Printable& x) { return x.printTo(*this); } diff --git a/cores/esp8266/Print.h b/cores/esp8266/Print.h index 6a64ba4be..79358f157 100644 --- a/cores/esp8266/Print.h +++ b/cores/esp8266/Print.h @@ -63,6 +63,7 @@ class Print { return write((const uint8_t *) buffer, size); } + size_t print(const __FlashStringHelper *); size_t print(const String &); size_t print(const char[]); size_t print(char); @@ -74,6 +75,7 @@ class Print { size_t print(double, int = 2); size_t print(const Printable&); + size_t println(const __FlashStringHelper *); size_t println(const String &s); size_t println(const char[]); size_t println(char); diff --git a/cores/esp8266/WString.cpp b/cores/esp8266/WString.cpp index ab523677b..61fc5ac94 100644 --- a/cores/esp8266/WString.cpp +++ b/cores/esp8266/WString.cpp @@ -4,6 +4,7 @@ Copyright (c) 2009-10 Hernando Barragan. All rights reserved. Copyright 2011, Paul Stoffregen, paul@pjrc.com Modified by Ivan Grokhotkov, 2014 - esp8266 support + Modified by Michael C. Miller, 2015 - esp8266 progmem support This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -44,6 +45,11 @@ ICACHE_FLASH_ATTR String::String(const String &value) { *this = value; } +ICACHE_FLASH_ATTR String::String(const __FlashStringHelper *pstr) { + init(); + *this = pstr; // see operator = +} + #ifdef __GXX_EXPERIMENTAL_CXX0X__ ICACHE_FLASH_ATTR String::String(String &&rval) { init(); @@ -167,6 +173,16 @@ 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) { + if (!reserve(length)) { + invalidate(); + return *this; + } + len = length; + strcpy_P(buffer, (PGM_P)pstr); + return *this; +} + #ifdef __GXX_EXPERIMENTAL_CXX0X__ void ICACHE_FLASH_ATTR String::move(String &rhs) { if(buffer) { @@ -223,6 +239,14 @@ String & ICACHE_FLASH_ATTR String::operator =(const char *cstr) { return *this; } +String & ICACHE_FLASH_ATTR String::operator = (const __FlashStringHelper *pstr) +{ + if (pstr) copy(pstr, strlen_P((PGM_P)pstr)); + else invalidate(); + + return *this; +} + // /*********************************************/ // /* concat */ // /*********************************************/ @@ -299,6 +323,17 @@ unsigned char ICACHE_FLASH_ATTR String::concat(double num) { return concat(string, strlen(string)); } +unsigned char ICACHE_FLASH_ATTR String::concat(const __FlashStringHelper * str) { + if (!str) return 0; + int length = strlen_P((PGM_P)str); + if (length == 0) return 1; + unsigned int newlen = len + length; + if (!reserve(newlen)) return 0; + strcpy_P(buffer + len, (PGM_P)str); + len = newlen; + return 1; +} + /*********************************************/ /* Concatenate */ /*********************************************/ @@ -373,6 +408,13 @@ StringSumHelper & ICACHE_FLASH_ATTR operator +(const StringSumHelper &lhs, doubl return a; } +StringSumHelper & ICACHE_FLASH_ATTR operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(rhs)) a.invalidate(); + return a; +} + // /*********************************************/ // /* Comparison */ // /*********************************************/ diff --git a/cores/esp8266/WString.h b/cores/esp8266/WString.h index 6ca037483..531fc88c8 100644 --- a/cores/esp8266/WString.h +++ b/cores/esp8266/WString.h @@ -26,15 +26,17 @@ #include #include #include -#define PROGMEM +#include // An inherited class for holding the result of a concatenation. These // result objects are assumed to be writable by subsequent concatenations. class StringSumHelper; -typedef char* __FlashStringHelper; -//#define F(str) []() -> const char * { static const char tmp[] ICACHE_RODATA_ATTR = str; return &tmp[0]; }() -#define F(str) str +// an abstract class used as a means to proide a unique pointer type +// but really has no body +class __FlashStringHelper; +#define F(string_literal) (reinterpret_cast(PSTR(string_literal))) + // The string class class String { @@ -53,6 +55,7 @@ class String { // be false). String(const char *cstr = ""); String(const String &str); + String(const __FlashStringHelper *str); #ifdef __GXX_EXPERIMENTAL_CXX0X__ String(String &&rval); String(StringSumHelper &&rval); @@ -81,6 +84,7 @@ class String { // marked as invalid ("if (s)" will be false). String & operator =(const String &rhs); String & operator =(const char *cstr); + String & operator = (const __FlashStringHelper *str); #ifdef __GXX_EXPERIMENTAL_CXX0X__ String & operator =(String &&rval); String & operator =(StringSumHelper &&rval); @@ -101,6 +105,7 @@ class String { unsigned char concat(unsigned long num); unsigned char concat(float num); unsigned char concat(double num); + unsigned char concat(const __FlashStringHelper * str); // if there's not enough memory for the concatenated value, the string // will be left unchanged (but this isn't signalled in any way) @@ -144,6 +149,10 @@ class String { concat(num); return (*this); } + String & operator += (const __FlashStringHelper *str){ + concat(str); + return (*this); + } friend StringSumHelper & operator +(const StringSumHelper &lhs, const String &rhs); friend StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr); @@ -155,6 +164,7 @@ class String { friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned long num); friend StringSumHelper & operator +(const StringSumHelper &lhs, float num); friend StringSumHelper & operator +(const StringSumHelper &lhs, double num); + friend StringSumHelper & operator +(const StringSumHelper &lhs, const __FlashStringHelper *rhs); // comparison (only works w/ Strings and "strings") operator StringIfHelperType() const { @@ -237,6 +247,7 @@ class String { // copy and move String & copy(const char *cstr, unsigned int length); + String & copy(const __FlashStringHelper *pstr, unsigned int length); #ifdef __GXX_EXPERIMENTAL_CXX0X__ void move(String &rhs); #endif diff --git a/cores/esp8266/debug.cpp b/cores/esp8266/debug.cpp new file mode 100644 index 000000000..5e280122e --- /dev/null +++ b/cores/esp8266/debug.cpp @@ -0,0 +1,35 @@ +/* + debug.cpp - debug helper functions + Copyright (c) 2015 Markus Sattler. 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 + 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 "Arduino.h" +#include "debug.h" + +void ICACHE_RAM_ATTR hexdump(uint8_t *mem, uint32_t len, uint8_t cols) { + os_printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", mem, len, len); + for(uint32_t i = 0; i < len; i++) { + if(i % cols == 0) { + os_printf("\n[0x%08X] 0x%08X: ", mem, i); + } + os_printf("%02X ", *mem); + mem++; + } + os_printf("\n"); +} + diff --git a/cores/esp8266/debug.h b/cores/esp8266/debug.h index a312bfdfd..cf0830d3e 100644 --- a/cores/esp8266/debug.h +++ b/cores/esp8266/debug.h @@ -3,6 +3,9 @@ #include // #define DEBUGV(...) ets_printf(__VA_ARGS__) -#define DEBUGV(...) +#define DEBUGV(...) + +void hexdump(uint8_t *mem, uint32_t len, uint8_t cols = 16); + #endif//ARD_DEBUG_H diff --git a/cores/esp8266/libc_replacements.c b/cores/esp8266/libc_replacements.c index c1abbcf6f..64efd94ab 100644 --- a/cores/esp8266/libc_replacements.c +++ b/cores/esp8266/libc_replacements.c @@ -116,7 +116,7 @@ char* strncpy(char * dest, const char * src, size_t n) { return ets_strncpy(dest, src, n); } -size_t strnlen(const char *s, size_t len) { +size_t ICACHE_FLASH_ATTR strnlen(const char *s, size_t len) { // there is no ets_strnlen const char *cp; for (cp = s; len != 0 && *cp != '\0'; cp++, len--); @@ -127,7 +127,7 @@ char* strstr(const char *haystack, const char *needle) { return ets_strstr(haystack, needle); } -char* strchr(const char * str, int character) { +char* ICACHE_FLASH_ATTR strchr(const char * str, int character) { while(1) { if(*str == 0x00) { return NULL; @@ -139,7 +139,7 @@ char* strchr(const char * str, int character) { } } -char * strrchr(const char * str, int character) { +char * ICACHE_FLASH_ATTR strrchr(const char * str, int character) { char * ret = NULL; while(1) { if(*str == 0x00) { @@ -223,7 +223,7 @@ char* ICACHE_FLASH_ATTR strtok(char * str, const char * delimiters) { return ret; } -int strcasecmp(const char * str1, const char * str2) { +int ICACHE_FLASH_ATTR strcasecmp(const char * str1, const char * str2) { int d = 0; while(1) { int c1 = tolower(*str1++); diff --git a/cores/esp8266/pgmspace.cpp b/cores/esp8266/pgmspace.cpp new file mode 100644 index 000000000..84af6264b --- /dev/null +++ b/cores/esp8266/pgmspace.cpp @@ -0,0 +1,161 @@ +/* +pgmspace.cpp - string functions that support PROGMEM +Copyright (c) 2015 Michael C. Miller. 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 +*/ + +#include +#include "pgmspace.h" + +size_t ICACHE_FLASH_ATTR strnlen_P(const char* s, size_t size) { + const char* cp; + for (cp = s; size != 0 && pgm_read_byte(cp) != '\0'; cp++, size--); + return (size_t)(cp - s); +} + +void* ICACHE_FLASH_ATTR memcpy_P(void* dest, const void* src, size_t count) { + const uint8_t* read = reinterpret_cast(src); + uint8_t* write = reinterpret_cast(dest); + + while (count) + { + *write++ = pgm_read_byte(read++); + count--; + } + + return dest; +} + +char* ICACHE_FLASH_ATTR strncpy_P(char* dest, const char* src, size_t size) { + const char* read = src; + char* write = dest; + char ch = '.'; + while (size > 0 && ch != '\0') + { + ch = pgm_read_byte(read++); + *write++ = ch; + size--; + } + + return dest; +} + +char* ICACHE_FLASH_ATTR strncat_P(char* dest, const char* src, size_t size) { + char* write = dest; + + while (*write != '\0') + { + write++; + } + + const char* read = src; + char ch = '.'; + + while (size > 0 && ch != '\0') + { + ch = pgm_read_byte(read++); + *write++ = ch; + + size--; + } + + if (ch != '\0') + { + *write = '\0'; + } + + return dest; +} + +int ICACHE_FLASH_ATTR strncmp_P(const char* str1, const char* str2P, size_t size) { + int result = 0; + + while (size > 0) + { + char ch1 = *str1++; + char ch2 = pgm_read_byte(str2P++); + result = ch1 - ch2; + if (result != 0 || ch2 == '\0') + { + break; + } + + size--; + } + + return result; +} + +int ICACHE_FLASH_ATTR strncasecmp_P(const char* str1, const char* str2P, size_t size) { + int result = 0; + + while (size > 0) + { + char ch1 = tolower(*str1++); + char ch2 = tolower(pgm_read_byte(str2P++)); + result = ch1 - ch2; + if (result != 0 || ch2 == '\0') + { + break; + } + + size--; + } + + return result; +} + +int ICACHE_FLASH_ATTR printf_P(const char* formatP, ...) { + int ret; + va_list arglist; + va_start(arglist, formatP); + + size_t fmtLen = strlen_P(formatP); + char* format = new char[fmtLen + 1]; + strcpy_P(format, formatP); + + ret = os_printf(format, arglist); + + delete [] format; + + va_end(arglist); + return ret; +} + +int ICACHE_FLASH_ATTR snprintf_P(char* str, size_t strSize, const char* formatP, ...) { + int ret; + va_list arglist; + va_start(arglist, formatP); + + ret = vsnprintf_P(str, strSize, formatP, arglist); + + va_end(arglist); + return ret; +} + +int ICACHE_FLASH_ATTR vsnprintf_P(char* str, size_t strSize, const char* formatP, va_list ap) { + int ret; + + size_t fmtLen = strlen_P(formatP); + char* format = new char[fmtLen + 1]; + strcpy_P(format, formatP); + + ret = ets_vsnprintf(str, strSize, format, ap); + + delete [] format; + + return ret; +} \ No newline at end of file diff --git a/cores/esp8266/pgmspace.h b/cores/esp8266/pgmspace.h index 506c8f8d3..695f2a50b 100644 --- a/cores/esp8266/pgmspace.h +++ b/cores/esp8266/pgmspace.h @@ -12,13 +12,11 @@ extern "C" { } #endif -#define PROGMEM +#define PROGMEM ICACHE_RODATA_ATTR #define PGM_P const char * -#define PSTR(str) (str) +#define PGM_VOID_P const void * +#define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];})) -#define vsnprintf_P(...) ets_vsnprintf( __VA_ARGS__ ) -#define snprintf_P(...) snprintf( __VA_ARGS__ ) -#define printf_P(...) os_printf(__VA_ARGS__) #define _SFR_BYTE(n) (n) @@ -32,23 +30,56 @@ typedef uint16_t prog_uint16_t; typedef int32_t prog_int32_t; typedef uint32_t prog_uint32_t; -#define memcpy_P(dest, src, num) memcpy((dest), (src), (num)) -#define strcpy_P(dest, src) strcpy((dest), (src)) -#define strcat_P(dest, src) strcat((dest), (src)) -#define strcmp_P(a, b) strcmp((a), (b)) -#define strstr_P(a, b) strstr((a), (b)) -#define strlen_P(s) strlen((const char *)(s)) -#define strcasecmp_P(a, b) strcasecmp((a), (b)) -#define strncpy_P(dest, src, size) strncpy((dest), (src), (size)) -#define strncat_P(dest, src, size) strncat((dest), (src), (size)) -#define strncmp_P(a, b, size) strncmp((a), (b), (size)) -#define strnlen_P(s, size) strnlen((const char *)(s), (size)) -#define strncasecmp_P(a, b, size) strncasecmp((a), (b), (size)) +#define SIZE_IRRELEVANT 0x7fffffff -#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) -#define pgm_read_word(addr) (*(const unsigned short *)(addr)) -#define pgm_read_dword(addr) (*(const unsigned long *)(addr)) -#define pgm_read_float(addr) (*(const float *)(addr)) +extern void* memcpy_P(void* dest, const void* src, size_t count); + +extern char* strncpy_P(char* dest, const char* src, size_t size); +#define strcpy_P(dest, src) strncpy_P((dest), (src), SIZE_IRRELEVANT) + +extern char* strncat_P(char* dest, const char* src, size_t size); +#define strcat_P(dest, src) strncat_P((dest), (src), SIZE_IRRELEVANT) + +extern int strncmp_P(const char* str1, const char* str2P, size_t size); +#define strcmp_P(str1, str2P) strncmp_P((str1), (str2P), SIZE_IRRELEVANT) + +extern int strncasecmp_P(const char* str1, const char* str2P, size_t size); +#define strcasecmp_P(str1, str2P) strncasecmp_P((str1), (str2P), SIZE_IRRELEVANT) + +extern size_t strnlen_P(const char *s, size_t size); +#define strlen_P(strP) strnlen_P((strP), SIZE_IRRELEVANT) + +extern int printf_P(const char *formatP, ...); +extern int snprintf_P(char *str, size_t strSize, const char *formatP, ...); +extern int vsnprintf_P(char *str, size_t strSize, const char *formatP, va_list ap); + +// flash memory must be read using 32 bit aligned addresses else a processor +// exception will be triggered +// order within the 32 bit values are +// -------------- +// b3, b2, b1, b0 +// w1, w0 + +#define pgm_read_byte(addr) \ +(__extension__({ \ + PGM_P __local = (PGM_P)(addr); /* isolate varible for macro expansion */ \ + ptrdiff_t __offset = ((uint32_t)__local & 0x00000003); /* byte aligned mask */ \ + const uint32_t* __addr32 = reinterpret_cast(reinterpret_cast(__local)-__offset); \ + uint8_t __result = ((*__addr32) >> (__offset * 8)); \ + __result; \ +})) + +#define pgm_read_word(addr) \ +(__extension__({ \ + PGM_P __local = (PGM_P)(addr); /* isolate varible for macro expansion */ \ + ptrdiff_t __offset = ((uint32_t)__local & 0x00000002); /* word aligned mask */ \ + const uint32_t* __addr32 = reinterpret_cast(reinterpret_cast(__local) - __offset); \ + uint16_t __result = ((*__addr32) >> (__offset * 8)); \ + __result; \ +})) + +#define pgm_read_dword(addr) (*reinterpret_cast(addr)) +#define pgm_read_float(addr) (*reinterpret_cast(addr)) #define pgm_read_byte_near(addr) pgm_read_byte(addr) #define pgm_read_word_near(addr) pgm_read_word(addr) diff --git a/cores/esp8266/spiffs/spiffs.c b/cores/esp8266/spiffs/spiffs.c index d739795ed..c07be839a 100755 --- a/cores/esp8266/spiffs/spiffs.c +++ b/cores/esp8266/spiffs/spiffs.c @@ -8,21 +8,17 @@ static u8_t spiffs_work_buf[LOG_PAGE_SIZE*2]; static u8_t spiffs_fds[32*4]; static u8_t spiffs_cache[(LOG_PAGE_SIZE+32)*4]; -static s32_t api_spiffs_read(u32_t addr, u32_t size, u8_t *dst) -{ +static s32_t api_spiffs_read(u32_t addr, u32_t size, u8_t *dst){ flashmem_read(dst, addr, size); return SPIFFS_OK; } -static s32_t api_spiffs_write(u32_t addr, u32_t size, u8_t *src) -{ - //debugf("api_spiffs_write"); +static s32_t api_spiffs_write(u32_t addr, u32_t size, u8_t *src){ flashmem_write(src, addr, size); return SPIFFS_OK; } -static s32_t api_spiffs_erase(u32_t addr, u32_t size) -{ +static s32_t api_spiffs_erase(u32_t addr, u32_t size){ debugf("api_spiffs_erase"); u32_t sect_first = flashmem_get_sector_of_address(addr); u32_t sect_last = sect_first; @@ -45,48 +41,38 @@ extern uint32_t _SPIFFS_end; spiffs_config spiffs_get_storage_config() { spiffs_config cfg = {0}; + if ((u32_t)&_SPIFFS_start == 0) return cfg; cfg.phys_addr = (u32_t)&_SPIFFS_start; - if (cfg.phys_addr == 0) - return cfg; - cfg.phys_addr += 0x3000; - cfg.phys_addr &= 0xFFFFC000; // align to 4 sector. cfg.phys_size = (u32_t)((u32_t)&_SPIFFS_end - (u32_t)&_SPIFFS_start); - /*cfg.phys_addr = INTERNAL_FLASH_SIZE - SPIFFS_WORK_SIZE + INTERNAL_FLASH_START_ADDRESS; - cfg.phys_addr += 0x3000; - cfg.phys_addr &= 0xFFFFC000; // align to 4 sector. - cfg.phys_size = SPIFFS_WORK_SIZE;*/ cfg.phys_erase_block = INTERNAL_FLASH_SECTOR_SIZE; // according to datasheet cfg.log_block_size = INTERNAL_FLASH_SECTOR_SIZE * 2; // Important to make large cfg.log_page_size = LOG_PAGE_SIZE; // as we said return cfg; } -bool spiffs_format_internal() -{ +bool spiffs_format_internal(){ spiffs_config cfg = spiffs_get_storage_config(); - if (cfg.phys_addr == 0) - { - SYSTEM_ERROR("Can't format file system, wrong address"); - return false; + if (cfg.phys_addr == 0){ + SYSTEM_ERROR("Can't format file system, wrong address"); + return false; } u32_t sect_first, sect_last; - sect_first = cfg.phys_addr; - sect_first = flashmem_get_sector_of_address((u32_t)&_SPIFFS_start); + sect_first = flashmem_get_first_free_block_address(); sect_last = flashmem_get_sector_of_address((u32_t)&_SPIFFS_end); debugf("sect_first: %x, sect_last: %x\n", sect_first, sect_last); - while( sect_first <= sect_last ) - if(!flashmem_erase_sector( sect_first ++ )) - return false; + while( sect_first <= sect_last ){ + if(!flashmem_erase_sector( sect_first ++ )) + return false; + } + return true; } -void spiffs_mount() -{ +bool spiffs_mount(){ spiffs_config cfg = spiffs_get_storage_config(); - if (cfg.phys_addr == 0) - { - SYSTEM_ERROR("Can't start file system, wrong address"); - return; + if (cfg.phys_addr == 0){ + SYSTEM_ERROR("Can't start file system, wrong address"); + return false; } debugf("fs.start:%x, size:%d Kb\n", cfg.phys_addr, cfg.phys_size / 1024); @@ -94,17 +80,18 @@ void spiffs_mount() cfg.hal_read_f = api_spiffs_read; cfg.hal_write_f = api_spiffs_write; cfg.hal_erase_f = api_spiffs_erase; - + uint32_t dat; bool writeFirst = false; flashmem_read(&dat, cfg.phys_addr, 4); - //debugf("%X", dat); - if (dat == UINT32_MAX) - { - debugf("First init file system"); - spiffs_format_internal(); - writeFirst = true; + if (dat == UINT32_MAX){ + debugf("First init file system"); + if(!spiffs_format_internal()){ + SYSTEM_ERROR("Can't format file system"); + return false; + } + writeFirst = true; } int res = SPIFFS_mount(&_filesystemStorageHandle, @@ -116,66 +103,44 @@ void spiffs_mount() sizeof(spiffs_cache), NULL); debugf("mount res: %d\n", res); - - if (writeFirst) - { - file_t fd = SPIFFS_open(&_filesystemStorageHandle, "initialize_fs_header.dat", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0); - SPIFFS_write(&_filesystemStorageHandle, fd, (u8_t *)"1", 1); - SPIFFS_fremove(&_filesystemStorageHandle, fd); - SPIFFS_close(&_filesystemStorageHandle, fd); + + if(res != 0) return false; + + if (writeFirst){ + file_t fd = SPIFFS_open(&_filesystemStorageHandle, "initialize_fs_header.dat", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0); + SPIFFS_write(&_filesystemStorageHandle, fd, (u8_t *)"1", 1); + SPIFFS_fremove(&_filesystemStorageHandle, fd); + SPIFFS_close(&_filesystemStorageHandle, fd); } - - //dat=0; - //flashmem_read(&dat, cfg.phys_addr, 4); - //debugf("%X", dat); + return true; } -void spiffs_unmount() -{ +void spiffs_unmount(){ SPIFFS_unmount(&_filesystemStorageHandle); } -// FS formatting function -bool spiffs_format() -{ +bool spiffs_format(){ spiffs_unmount(); - spiffs_format_internal(); + if(!spiffs_format_internal()) return false; spiffs_mount(); return true; } -//int spiffs_check( void ) -//{ - // ets_wdt_disable(); - // int res = (int)SPIFFS_check(&_filesystemStorageHandle); - // ets_wdt_enable(); - // return res; -//} - -void test_spiffs() -{ +void test_spiffs(){ char buf[12] = {0}; - - // Surely, I've mounted spiffs before entering here - spiffs_file fd; spiffs_stat st = {0}; SPIFFS_stat(&_filesystemStorageHandle, "my_file.txt", &st); - if (st.size <= 0) - { - fd = SPIFFS_open(&_filesystemStorageHandle, "my_file.txt", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0); - if (SPIFFS_write(&_filesystemStorageHandle, fd, (u8_t *)"Hello world", 11) < 0) - debugf("errno %d\n", SPIFFS_errno(&_filesystemStorageHandle)); - SPIFFS_close(&_filesystemStorageHandle, fd); - debugf("file created"); - } - else - debugf("file %s exist :)", st.name); - + if (st.size <= 0){ + fd = SPIFFS_open(&_filesystemStorageHandle, "my_file.txt", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0); + if (SPIFFS_write(&_filesystemStorageHandle, fd, (u8_t *)"Hello world", 11) < 0) + debugf("errno %d\n", SPIFFS_errno(&_filesystemStorageHandle)); + SPIFFS_close(&_filesystemStorageHandle, fd); + debugf("file created"); + } else debugf("file %s exist :)", st.name); fd = SPIFFS_open(&_filesystemStorageHandle, "my_file.txt", SPIFFS_RDWR, 0); if (SPIFFS_read(&_filesystemStorageHandle, fd, (u8_t *)buf, 11) < 0) debugf("errno %d\n", SPIFFS_errno(&_filesystemStorageHandle)); SPIFFS_close(&_filesystemStorageHandle, fd); - debugf("--> %s <--\n", buf); } diff --git a/cores/esp8266/spiffs/spiffs.h b/cores/esp8266/spiffs/spiffs.h index 85f7de7f1..ad922b4a8 100755 --- a/cores/esp8266/spiffs/spiffs.h +++ b/cores/esp8266/spiffs/spiffs.h @@ -83,12 +83,10 @@ typedef enum { } spiffs_check_report; /* file system check callback function */ -typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_report report, - u32_t arg1, u32_t arg2); +typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_report report, u32_t arg1, u32_t arg2); #ifndef SPIFFS_DBG -#define SPIFFS_DBG(...) \ - print(__VA_ARGS__) +#define SPIFFS_DBG(...) printf(__VA_ARGS__) #endif #ifndef SPIFFS_GC_DBG #define SPIFFS_GC_DBG(...) printf(__VA_ARGS__) @@ -456,7 +454,7 @@ u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages); #endif -void spiffs_mount(); +bool spiffs_mount(); void spiffs_unmount(); bool spiffs_format(); spiffs_config spiffs_get_storage_config(); diff --git a/cores/esp8266/spiffs/spiffs_cache.c b/cores/esp8266/spiffs/spiffs_cache.c index a4fec5c2e..5bfe51e86 100755 --- a/cores/esp8266/spiffs/spiffs_cache.c +++ b/cores/esp8266/spiffs/spiffs_cache.c @@ -20,7 +20,7 @@ static spiffs_cache_page *spiffs_cache_page_get(spiffs *fs, spiffs_page_ix pix) if ((cache->cpage_use_map & (1<flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 && cp->pix == pix ) { - SPIFFS_CACHE_DBG("CACHE_GET: have cache page %u for %04x\n", i, pix); + SPIFFS_CACHE_DBG("CACHE_GET: have cache page %d for %04x\n", i, pix); cp->last_access = cache->last_access; return cp; } @@ -46,9 +46,9 @@ static s32_t spiffs_cache_page_free(spiffs *fs, int ix, u8_t write_back) { cache->cpage_use_map &= ~(1 << ix); if (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) { - SPIFFS_CACHE_DBG("CACHE_FREE: free cache page %u objid %04x\n", ix, cp->obj_id); + SPIFFS_CACHE_DBG("CACHE_FREE: free cache page %d objid %04x\n", ix, cp->obj_id); } else { - SPIFFS_CACHE_DBG("CACHE_FREE: free cache page %u pix %04x\n", ix, cp->pix); + SPIFFS_CACHE_DBG("CACHE_FREE: free cache page %d pix %04x\n", ix, cp->pix); } } @@ -98,7 +98,7 @@ static spiffs_cache_page *spiffs_cache_page_allocate(spiffs *fs) { spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i); cache->cpage_use_map |= (1<last_access = cache->last_access; - SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page %u\n", i); + SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page %d\n", i); return cp; } } diff --git a/libraries/ESP8266WebServer/examples/SDWebServer/SDWebServer.ino b/libraries/ESP8266WebServer/examples/SDWebServer/SDWebServer.ino index dcb3a9d6e..3b42659ab 100644 --- a/libraries/ESP8266WebServer/examples/SDWebServer/SDWebServer.ino +++ b/libraries/ESP8266WebServer/examples/SDWebServer/SDWebServer.ino @@ -55,7 +55,6 @@ void returnOK(){ message += "Access-Control-Allow-Origin: *\r\n"; message += "\r\n"; client.print(message); - message = 0; client.stop(); } @@ -69,7 +68,6 @@ void returnFail(String msg){ message += msg; message += "\r\n"; client.print(message); - message = 0; client.stop(); } @@ -108,8 +106,8 @@ bool loadFromSdCard(String path){ head += "\r\nAccess-Control-Allow-Origin: *"; head += "\r\n\r\n"; client.print(head); - dataType = 0; - path = 0; + dataType = String(); + path = String(); if(client.write(dataFile) != dataFile.size()){ DBG_OUTPUT_PORT.println("Sent less data than expected!"); @@ -159,11 +157,11 @@ void deleteRecursive(String path){ entry.close(); SD.remove((char *)entryPath.c_str()); } - entryPath = 0; + entryPath = String(); yield(); } SD.rmdir((char *)path.c_str()); - path = 0; + path = String(); file.close(); } @@ -173,7 +171,7 @@ void handleDelete(){ if(path == "/" || !SD.exists((char *)path.c_str())) return returnFail("BAD PATH"); deleteRecursive(path); returnOK(); - path = 0; + path = String(); } void handleCreate(){ @@ -190,7 +188,7 @@ void handleCreate(){ SD.mkdir((char *)path.c_str()); } returnOK(); - path = 0; + path = String(); } void printDirectory() { @@ -198,7 +196,7 @@ void printDirectory() { String path = server.arg("dir"); if(path != "/" && !SD.exists((char *)path.c_str())) return returnFail("BAD PATH"); File dir = SD.open((char *)path.c_str()); - path = 0; + path = String(); if(!dir.isDirectory()){ dir.close(); return returnFail("NOT DIR"); @@ -229,7 +227,7 @@ void printDirectory() { output += "]"; client.write(output.c_str(), output.length()); client.stop(); - output = 0; + output = String(); } void handleNotFound(){ diff --git a/libraries/SD/src/SD.h b/libraries/SD/src/SD.h index 449984219..93c79138b 100644 --- a/libraries/SD/src/SD.h +++ b/libraries/SD/src/SD.h @@ -48,6 +48,28 @@ public: boolean isDirectory(void); File openNextFile(uint8_t mode = O_RDONLY); void rewindDirectory(void); + + template size_t write(T &src){ + uint8_t obuf[512]; + size_t doneLen = 0; + size_t sentLen; + int i; + + while (src.available() > 512){ + src.read(obuf, 512); + sentLen = write(obuf, 512); + doneLen = doneLen + sentLen; + if(sentLen != 512){ + return doneLen; + } + } + + size_t leftLen = src.available(); + src.read(obuf, leftLen); + sentLen = write(obuf, leftLen); + doneLen = doneLen + sentLen; + return doneLen; + } using Print::write; }; diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp index be4627740..c96c4fcb8 100644 --- a/libraries/SPI/SPI.cpp +++ b/libraries/SPI/SPI.cpp @@ -308,6 +308,13 @@ void SPIClass::write32(uint32_t data, bool msb) { while(SPI1CMD & SPIBUSY) {} } +/** + * Note: + * data need to be aligned to 32Bit + * or you get an Fatal exception (9) + * @param data uint8_t * + * @param size uint32_t + */ void SPIClass::writeBytes(uint8_t * data, uint32_t size) { while(size) { if(size > 64) { @@ -340,6 +347,15 @@ void SPIClass::writeBytes_(uint8_t * data, uint8_t size) { while(SPI1CMD & SPIBUSY) {} } + +/** + * Note: + * data need to be aligned to 32Bit + * or you get an Fatal exception (9) + * @param data uint8_t * + * @param size uint8_t max for size is 64Byte + * @param repeat uint32_t + */ void SPIClass::writePattern(uint8_t * data, uint8_t size, uint32_t repeat) { if(size > 64) return; //max Hardware FIFO @@ -376,6 +392,14 @@ void SPIClass::writePattern_(uint8_t * data, uint8_t size, uint8_t repeat) { writeBytes(&buffer[0], bytes); } +/** + * Note: + * in and out need to be aligned to 32Bit + * or you get an Fatal exception (9) + * @param out uint8_t * + * @param in uint8_t * + * @param size uint32_t + */ void SPIClass::transferBytes(uint8_t * out, uint8_t * in, uint32_t size) { while(size) { if(size > 64) {