mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-07 16:23:38 +03:00
Merge branch 'esp8266' of https://github.com/ficeto/Arduino into ficeto-esp8266
This commit is contained in:
commit
dea91ca620
@ -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"
|
||||
|
@ -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);
|
||||
}
|
||||
*/
|
||||
|
@ -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<typename T> 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
|
||||
|
@ -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 <stdlib.h>
|
||||
@ -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<PGM_P>(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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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<StringSumHelper&>(lhs);
|
||||
if (!a.concat(rhs)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
// /*********************************************/
|
||||
// /* Comparison */
|
||||
// /*********************************************/
|
||||
|
@ -26,15 +26,17 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#define PROGMEM
|
||||
#include <pgmspace.h>
|
||||
|
||||
// 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<const __FlashStringHelper *>(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
|
||||
|
35
cores/esp8266/debug.cpp
Normal file
35
cores/esp8266/debug.cpp
Normal file
@ -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");
|
||||
}
|
||||
|
@ -3,6 +3,9 @@
|
||||
|
||||
#include <stddef.h>
|
||||
// #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
|
||||
|
@ -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++);
|
||||
|
161
cores/esp8266/pgmspace.cpp
Normal file
161
cores/esp8266/pgmspace.cpp
Normal file
@ -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 <ctype.h>
|
||||
#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<const uint8_t*>(src);
|
||||
uint8_t* write = reinterpret_cast<uint8_t*>(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;
|
||||
}
|
@ -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<const uint32_t*>(reinterpret_cast<const uint8_t*>(__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<const uint32_t*>(reinterpret_cast<const uint8_t*>(__local) - __offset); \
|
||||
uint16_t __result = ((*__addr32) >> (__offset * 8)); \
|
||||
__result; \
|
||||
}))
|
||||
|
||||
#define pgm_read_dword(addr) (*reinterpret_cast<const uint32_t*>(addr))
|
||||
#define pgm_read_float(addr) (*reinterpret_cast<const float*>(addr))
|
||||
|
||||
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
|
||||
#define pgm_read_word_near(addr) pgm_read_word(addr)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -20,7 +20,7 @@ static spiffs_cache_page *spiffs_cache_page_get(spiffs *fs, spiffs_page_ix pix)
|
||||
if ((cache->cpage_use_map & (1<<i)) &&
|
||||
(cp->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<<i);
|
||||
cp->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;
|
||||
}
|
||||
}
|
||||
|
@ -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(){
|
||||
|
@ -48,6 +48,28 @@ public:
|
||||
boolean isDirectory(void);
|
||||
File openNextFile(uint8_t mode = O_RDONLY);
|
||||
void rewindDirectory(void);
|
||||
|
||||
template<typename T> 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;
|
||||
};
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user