mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-19 23:22:16 +03:00
Merge branch 'ficeto-esp8266' into esp8266
* ficeto-esp8266: (31 commits) leftovers Update to the latest SPIFFS git and cleanup add Exception Causes (EXCCAUSE) docu fix possible null ptr in EEPROM.cpp Align the start of functions to the next power-of-two greater than 4, skipping up to 3 bytes. improve os_printf handling when buffer full. - wait for free buffer in hw fifo force all os_malloc calls to request a aligned size. - this fix Fatal exception (9) by unaligned class memory add some __attribute__ for compiler to get better optimizations and warning handle fix possible problems in EEPROM regarding interrupt handling and SPI flash blocking spiffs fixes improve includes add ssid and ip to debug out add examples/WiFiMulti/WiFiMulti.ino add support for list of AP connections - auto select ssid with best signal - for debugging enable DEBUG_WIFI_MULTI macro and call Serial.setDebugOutput(true); fix start address so erase works disable all interrupts when reading from spiffs printf to print instead of write fix uart triggering reset when spi has been read/written ESP8266WiFiClass::waitForConnectResult() add Print::printf fix data types ...
This commit is contained in:
commit
c32518974b
71
boards.txt
71
boards.txt
@ -2,7 +2,6 @@ menu.UploadSpeed=Upload Speed
|
|||||||
menu.CpuFrequency=CPU Frequency
|
menu.CpuFrequency=CPU Frequency
|
||||||
menu.FlashSize=Flash Size
|
menu.FlashSize=Flash Size
|
||||||
menu.FlashFreq=Flash Frequency
|
menu.FlashFreq=Flash Frequency
|
||||||
menu.FlashMode=Flash Mode
|
|
||||||
|
|
||||||
##############################################################
|
##############################################################
|
||||||
generic.name=Generic ESP8266 Module
|
generic.name=Generic ESP8266 Module
|
||||||
@ -24,6 +23,8 @@ generic.build.flash_mode=qio
|
|||||||
generic.build.flash_size=512K
|
generic.build.flash_size=512K
|
||||||
generic.build.flash_freq=40
|
generic.build.flash_freq=40
|
||||||
generic.build.flash_ld=eagle.flash.512k.ld
|
generic.build.flash_ld=eagle.flash.512k.ld
|
||||||
|
generic.build.spiffs_start=0x6B000
|
||||||
|
generic.build.spiffs_end=0x7B000
|
||||||
|
|
||||||
generic.menu.CpuFrequency.80=80 MHz
|
generic.menu.CpuFrequency.80=80 MHz
|
||||||
generic.menu.CpuFrequency.80.build.f_cpu=80000000L
|
generic.menu.CpuFrequency.80.build.f_cpu=80000000L
|
||||||
@ -49,39 +50,46 @@ generic.menu.UploadSpeed.512000.upload.speed=512000
|
|||||||
generic.menu.UploadSpeed.921600=921600
|
generic.menu.UploadSpeed.921600=921600
|
||||||
generic.menu.UploadSpeed.921600.upload.speed=921600
|
generic.menu.UploadSpeed.921600.upload.speed=921600
|
||||||
|
|
||||||
generic.menu.FlashSize.512K=512K
|
generic.menu.FlashSize.512K=512K (64K SPIFFS)
|
||||||
generic.menu.FlashSize.512K.build.flash_size=512K
|
generic.menu.FlashSize.512K.build.flash_size=512K
|
||||||
generic.menu.FlashSize.512K.build.flash_ld=eagle.flash.512k.ld
|
generic.menu.FlashSize.512K.build.flash_ld=eagle.flash.512k.ld
|
||||||
generic.menu.FlashSize.256K=256K
|
generic.menu.FlashSize.512K.build.spiffs_start=0x6B000
|
||||||
generic.menu.FlashSize.256K.build.flash_size=256K
|
generic.menu.FlashSize.512K.build.spiffs_end=0x7B000
|
||||||
generic.menu.FlashSize.256K.build.flash_ld=eagle.flash.256k.ld
|
generic.menu.FlashSize.1M512=1M (512K SPIFFS)
|
||||||
generic.menu.FlashSize.1M=1M
|
generic.menu.FlashSize.1M512.build.flash_size=1M
|
||||||
generic.menu.FlashSize.1M.build.flash_size=1M
|
generic.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld
|
||||||
generic.menu.FlashSize.1M.build.flash_ld=eagle.flash.1m.ld
|
generic.menu.FlashSize.1M512.build.spiffs_start=0x6B000
|
||||||
generic.menu.FlashSize.2M=2M
|
generic.menu.FlashSize.1M512.build.spiffs_end=0xFB000
|
||||||
|
generic.menu.FlashSize.1M256=1M (256K SPIFFS)
|
||||||
|
generic.menu.FlashSize.1M256.build.flash_size=1M
|
||||||
|
generic.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld
|
||||||
|
generic.menu.FlashSize.1M256.build.spiffs_start=0xAB000
|
||||||
|
generic.menu.FlashSize.1M256.build.spiffs_end=0xFB000
|
||||||
|
generic.menu.FlashSize.1M128=1M (128K SPIFFS)
|
||||||
|
generic.menu.FlashSize.1M128.build.flash_size=1M
|
||||||
|
generic.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld
|
||||||
|
generic.menu.FlashSize.1M128.build.spiffs_start=0xCB000
|
||||||
|
generic.menu.FlashSize.1M128.build.spiffs_end=0xFB000
|
||||||
|
generic.menu.FlashSize.1M64=1M (64K SPIFFS)
|
||||||
|
generic.menu.FlashSize.1M64.build.flash_size=1M
|
||||||
|
generic.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld
|
||||||
|
generic.menu.FlashSize.1M64.build.spiffs_start=0xEB000
|
||||||
|
generic.menu.FlashSize.1M64.build.spiffs_end=0xFB000
|
||||||
|
generic.menu.FlashSize.2M=2M (1M SPIFFS)
|
||||||
generic.menu.FlashSize.2M.build.flash_size=2M
|
generic.menu.FlashSize.2M.build.flash_size=2M
|
||||||
generic.menu.FlashSize.2M.build.flash_ld=eagle.flash.2m.ld
|
generic.menu.FlashSize.2M.build.flash_ld=eagle.flash.2m.ld
|
||||||
generic.menu.FlashSize.4M=4M
|
generic.menu.FlashSize.2M.build.spiffs_start=0x100000
|
||||||
|
generic.menu.FlashSize.2M.build.spiffs_end=0x1FB000
|
||||||
|
generic.menu.FlashSize.4M=4M (3M SPIFFS)
|
||||||
generic.menu.FlashSize.4M.build.flash_size=4M
|
generic.menu.FlashSize.4M.build.flash_size=4M
|
||||||
generic.menu.FlashSize.4M.build.flash_ld=eagle.flash.4m.ld
|
generic.menu.FlashSize.4M.build.flash_ld=eagle.flash.4m.ld
|
||||||
|
generic.menu.FlashSize.4M.build.spiffs_start=0x100000
|
||||||
|
generic.menu.FlashSize.4M.build.spiffs_end=0x3FB000
|
||||||
|
|
||||||
generic.menu.FlashFreq.40=40MHz
|
# generic.menu.FlashFreq.40=40MHz
|
||||||
generic.menu.FlashFreq.40.build.flash_freq=40
|
# generic.menu.FlashFreq.40.build.flash_freq=40
|
||||||
generic.menu.FlashFreq.20=20MHz
|
# generic.menu.FlashFreq.80=80MHz
|
||||||
generic.menu.FlashFreq.20.build.flash_freq=20
|
# generic.menu.FlashFreq.80.build.flash_freq=80
|
||||||
generic.menu.FlashFreq.26=26.7MHz
|
|
||||||
generic.menu.FlashFreq.26.build.flash_freq=26.7
|
|
||||||
generic.menu.FlashFreq.80=80MHz
|
|
||||||
generic.menu.FlashFreq.80.build.flash_freq=80
|
|
||||||
|
|
||||||
generic.menu.FlashMode.qio=QIO
|
|
||||||
generic.menu.FlashMode.qio.build.flash_mode=qio
|
|
||||||
generic.menu.FlashMode.qout=QOUT
|
|
||||||
generic.menu.FlashMode.qout.build.flash_mode=qout
|
|
||||||
generic.menu.FlashMode.dio=DIO
|
|
||||||
generic.menu.FlashMode.dio.build.flash_mode=dio
|
|
||||||
generic.menu.FlashMode.dout=DOUT
|
|
||||||
generic.menu.FlashMode.dout.build.flash_mode=dout
|
|
||||||
|
|
||||||
##############################################################
|
##############################################################
|
||||||
modwifi.name=Olimex MOD-WIFI-ESP8266(-DEV)
|
modwifi.name=Olimex MOD-WIFI-ESP8266(-DEV)
|
||||||
@ -104,6 +112,8 @@ modwifi.build.flash_mode=qio
|
|||||||
modwifi.build.flash_size=2M
|
modwifi.build.flash_size=2M
|
||||||
modwifi.build.flash_freq=40
|
modwifi.build.flash_freq=40
|
||||||
modwifi.build.flash_ld=eagle.flash.2m.ld
|
modwifi.build.flash_ld=eagle.flash.2m.ld
|
||||||
|
modwifi.build.spiffs_start=0x100000
|
||||||
|
modwifi.build.spiffs_end=0x1FB000
|
||||||
|
|
||||||
modwifi.menu.CpuFrequency.80=80 MHz
|
modwifi.menu.CpuFrequency.80=80 MHz
|
||||||
modwifi.menu.CpuFrequency.80.build.f_cpu=80000000L
|
modwifi.menu.CpuFrequency.80.build.f_cpu=80000000L
|
||||||
@ -150,6 +160,8 @@ nodemcu.build.flash_mode=qio
|
|||||||
nodemcu.build.flash_size=4M
|
nodemcu.build.flash_size=4M
|
||||||
nodemcu.build.flash_freq=40
|
nodemcu.build.flash_freq=40
|
||||||
nodemcu.build.flash_ld=eagle.flash.4m.ld
|
nodemcu.build.flash_ld=eagle.flash.4m.ld
|
||||||
|
nodemcu.build.spiffs_start=0x100000
|
||||||
|
nodemcu.build.spiffs_end=0x3FB000
|
||||||
|
|
||||||
nodemcu.menu.CpuFrequency.80=80 MHz
|
nodemcu.menu.CpuFrequency.80=80 MHz
|
||||||
nodemcu.menu.CpuFrequency.80.build.f_cpu=80000000L
|
nodemcu.menu.CpuFrequency.80.build.f_cpu=80000000L
|
||||||
@ -176,9 +188,6 @@ nodemcu.menu.UploadSpeed.512000.upload.speed=512000
|
|||||||
nodemcu.menu.UploadSpeed.921600=921600
|
nodemcu.menu.UploadSpeed.921600=921600
|
||||||
nodemcu.menu.UploadSpeed.921600.upload.speed=921600
|
nodemcu.menu.UploadSpeed.921600.upload.speed=921600
|
||||||
|
|
||||||
nodemcu.menu.FlashSize.4M=4M
|
|
||||||
nodemcu.menu.FlashSize.4M.build.flash_size=4M
|
|
||||||
|
|
||||||
##############################################################
|
##############################################################
|
||||||
# wifio.name=Wifio
|
# wifio.name=Wifio
|
||||||
#
|
#
|
||||||
@ -197,6 +206,8 @@ nodemcu.menu.FlashSize.4M.build.flash_size=4M
|
|||||||
# wifio.build.flash_size=512K
|
# wifio.build.flash_size=512K
|
||||||
# wifio.build.flash_freq=40
|
# wifio.build.flash_freq=40
|
||||||
# wifio.build.flash_ld=eagle.flash.512k.ld
|
# wifio.build.flash_ld=eagle.flash.512k.ld
|
||||||
|
# wifio.build.spiffs_start=0x6B000
|
||||||
|
# wifio.build.spiffs_end=0x7B000
|
||||||
#
|
#
|
||||||
# wifio.menu.CpuFrequency.80=80MHz
|
# wifio.menu.CpuFrequency.80=80MHz
|
||||||
# wifio.menu.CpuFrequency.80.build.f_cpu=80000000L
|
# wifio.menu.CpuFrequency.80.build.f_cpu=80000000L
|
||||||
|
@ -135,7 +135,7 @@ void ets_intr_unlock();
|
|||||||
extern uint32_t interruptsState;
|
extern uint32_t interruptsState;
|
||||||
|
|
||||||
#define interrupts() xt_enable_interrupts(interruptsState)
|
#define interrupts() xt_enable_interrupts(interruptsState)
|
||||||
#define noInterrupts() xt_disable_interrupts(interruptsState, 15)
|
#define noInterrupts() __asm__ __volatile__("rsil %0,15; esync; isync; dsync" : "=a" (interruptsState))
|
||||||
|
|
||||||
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
|
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
|
||||||
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
|
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
|
||||||
|
199
cores/esp8266/FileSystem.cpp
Executable file → Normal file
199
cores/esp8266/FileSystem.cpp
Executable file → Normal file
@ -22,45 +22,72 @@
|
|||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
|
||||||
bool FSClass::mount() {
|
bool FSClass::mount() {
|
||||||
if (_mounted)
|
if(SPIFFS_mounted(&_filesystemStorageHandle)) return true;
|
||||||
return true;
|
int res = spiffs_mount();
|
||||||
|
if(res != 0){
|
||||||
_mounted = spiffs_mount();
|
int formated = SPIFFS_format(&_filesystemStorageHandle);
|
||||||
return _mounted;
|
if(formated != 0) return false;
|
||||||
|
res = spiffs_mount();
|
||||||
|
}
|
||||||
|
return (res == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FSClass::unmount() {
|
void FSClass::unmount() {
|
||||||
if (!_mounted)
|
if(SPIFFS_mounted(&_filesystemStorageHandle))
|
||||||
return;
|
SPIFFS_unmount(&_filesystemStorageHandle);
|
||||||
|
|
||||||
spiffs_unmount();
|
|
||||||
_mounted = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FSClass::format() {
|
bool FSClass::format() {
|
||||||
return spiffs_format();
|
if(!SPIFFS_mounted(&_filesystemStorageHandle)){
|
||||||
|
spiffs_mount();
|
||||||
|
}
|
||||||
|
SPIFFS_unmount(&_filesystemStorageHandle);
|
||||||
|
int formated = SPIFFS_format(&_filesystemStorageHandle);
|
||||||
|
if(formated != 0) return false;
|
||||||
|
return (spiffs_mount() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FSClass::exists(const char *filename) {
|
bool FSClass::check() {
|
||||||
|
return SPIFFS_check(&_filesystemStorageHandle) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FSClass::exists(char *filename) {
|
||||||
spiffs_stat stat = {0};
|
spiffs_stat stat = {0};
|
||||||
if (SPIFFS_stat(&_filesystemStorageHandle, filename, &stat) < 0)
|
if (SPIFFS_stat(&_filesystemStorageHandle, filename, &stat) < 0)
|
||||||
return false;
|
return false;
|
||||||
return stat.name[0] != '\0';
|
return stat.name[0] != '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FSClass::create(const char *filepath){
|
bool FSClass::create(char *filepath){
|
||||||
return SPIFFS_creat(&_filesystemStorageHandle, filepath, 0) == 0;
|
return SPIFFS_creat(&_filesystemStorageHandle, filepath, 0) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FSClass::remove(const char *filepath){
|
bool FSClass::remove(char *filepath){
|
||||||
return SPIFFS_remove(&_filesystemStorageHandle, filepath) == 0;
|
return SPIFFS_remove(&_filesystemStorageHandle, filepath) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FSClass::rename(const char *filename, const char *newname) {
|
bool FSClass::rename(char *filename, char *newname) {
|
||||||
return SPIFFS_rename(&_filesystemStorageHandle, filename, newname) == 0;
|
return SPIFFS_rename(&_filesystemStorageHandle, filename, newname) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FSFile FSClass::open(const char *filename, uint8_t mode) {
|
size_t FSClass::totalBytes(){
|
||||||
|
u32_t totalBytes;
|
||||||
|
u32_t usedBytes;
|
||||||
|
if(SPIFFS_info(&_filesystemStorageHandle, &totalBytes, &usedBytes) == 0)
|
||||||
|
return totalBytes;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FSClass::usedBytes(){
|
||||||
|
u32_t totalBytes;
|
||||||
|
u32_t usedBytes;
|
||||||
|
if(SPIFFS_info(&_filesystemStorageHandle, &totalBytes, &usedBytes) == 0)
|
||||||
|
return usedBytes;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSFile FSClass::open(char *filename, uint8_t mode) {
|
||||||
|
if(String(filename) == "" || String(filename) == "/") return FSFile("/");
|
||||||
int repeats = 0;
|
int repeats = 0;
|
||||||
bool notExist;
|
bool notExist;
|
||||||
bool canRecreate = (mode & SPIFFS_CREAT) == SPIFFS_CREAT;
|
bool canRecreate = (mode & SPIFFS_CREAT) == SPIFFS_CREAT;
|
||||||
@ -71,7 +98,7 @@ FSFile FSClass::open(const char *filename, uint8_t mode) {
|
|||||||
res = SPIFFS_open(&_filesystemStorageHandle, filename, (spiffs_flags)mode, 0);
|
res = SPIFFS_open(&_filesystemStorageHandle, filename, (spiffs_flags)mode, 0);
|
||||||
int code = SPIFFS_errno(&_filesystemStorageHandle);
|
int code = SPIFFS_errno(&_filesystemStorageHandle);
|
||||||
if (res < 0){
|
if (res < 0){
|
||||||
debugf("open errno %d\n", code);
|
SPIFFS_API_DBG_E("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);
|
notExist = (code == SPIFFS_ERR_NOT_FOUND || code == SPIFFS_ERR_DELETED || code == SPIFFS_ERR_FILE_DELETED || code == SPIFFS_ERR_IS_FREE);
|
||||||
if (notExist && canRecreate)
|
if (notExist && canRecreate)
|
||||||
remove(filename); // fix for deleted files
|
remove(filename); // fix for deleted files
|
||||||
@ -84,6 +111,14 @@ FSFile FSClass::open(const char *filename, uint8_t mode) {
|
|||||||
return FSFile();
|
return FSFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSFile FSClass::open(spiffs_dirent* entry, uint8_t mode){
|
||||||
|
int res = SPIFFS_open_by_dirent(&_filesystemStorageHandle, entry, (spiffs_flags)mode, 0);
|
||||||
|
if(res){
|
||||||
|
return FSFile(res);
|
||||||
|
}
|
||||||
|
return FSFile();
|
||||||
|
}
|
||||||
|
|
||||||
FSClass FS;
|
FSClass FS;
|
||||||
|
|
||||||
FSFile::FSFile() {
|
FSFile::FSFile() {
|
||||||
@ -91,95 +126,140 @@ FSFile::FSFile() {
|
|||||||
_stats = {0};
|
_stats = {0};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSFile::FSFile(String path) {
|
||||||
|
if(path == "/"){
|
||||||
|
_file = 0x1;
|
||||||
|
os_sprintf((char*)_stats.name, "%s", (char*)path.c_str());
|
||||||
|
_stats.size = 0;
|
||||||
|
_stats.type = SPIFFS_TYPE_DIR;
|
||||||
|
SPIFFS_opendir(&_filesystemStorageHandle, (char*)_stats.name, &_dir);
|
||||||
|
} else {
|
||||||
|
_file = SPIFFS_open(&_filesystemStorageHandle, (char *)path.c_str(), (spiffs_flags)FSFILE_READ, 0);
|
||||||
|
if(SPIFFS_fstat(&_filesystemStorageHandle, _file, &_stats) != 0){
|
||||||
|
SPIFFS_API_DBG_E("fstat errno %d\n", SPIFFS_errno(&_filesystemStorageHandle));
|
||||||
|
}
|
||||||
|
//debugf("FSFile name: %s, size: %d, type: %d\n", _stats.name, _stats.size, _stats.type);
|
||||||
|
if(_stats.type == SPIFFS_TYPE_DIR){
|
||||||
|
SPIFFS_opendir(&_filesystemStorageHandle, (char*)_stats.name, &_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FSFile::FSFile(file_t f) {
|
FSFile::FSFile(file_t f) {
|
||||||
_file = f;
|
_file = f;
|
||||||
if(SPIFFS_fstat(&_filesystemStorageHandle, _file, &_stats) != 0){
|
if(SPIFFS_fstat(&_filesystemStorageHandle, _file, &_stats) != 0){
|
||||||
debugf("mount errno %d\n", SPIFFS_errno(&_filesystemStorageHandle));
|
SPIFFS_API_DBG_E("fstat errno %d\n", SPIFFS_errno(&_filesystemStorageHandle));
|
||||||
|
}
|
||||||
|
//debugf("FSFile name: %s, size: %d, type: %d\n", _stats.name, _stats.size, _stats.type);
|
||||||
|
if(_stats.type == SPIFFS_TYPE_DIR){
|
||||||
|
SPIFFS_opendir(&_filesystemStorageHandle, (char*)_stats.name, &_dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FSFile::close() {
|
void FSFile::close() {
|
||||||
if (! _file) return;
|
if (! _file) return;
|
||||||
SPIFFS_close(&_filesystemStorageHandle, _file);
|
if(_stats.type == SPIFFS_TYPE_DIR){
|
||||||
|
SPIFFS_closedir(&_dir);
|
||||||
|
}
|
||||||
|
if(os_strlen((char*)_stats.name) > 1)
|
||||||
|
SPIFFS_close(&_filesystemStorageHandle, _file);
|
||||||
_file = 0;
|
_file = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char * FSFile::name(){
|
||||||
|
return (char*)_stats.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FSFile::isDirectory(void) {
|
||||||
|
return _stats.type == SPIFFS_TYPE_DIR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FSFile::rewindDirectory() {
|
||||||
|
if (!_file || !isDirectory()) return;
|
||||||
|
SPIFFS_closedir(&_dir);
|
||||||
|
SPIFFS_opendir(&_filesystemStorageHandle, (char*)_stats.name, &_dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSFile FSFile::openNextFile(){
|
||||||
|
if (!_file || !isDirectory()) return FSFile();
|
||||||
|
struct spiffs_dirent e;
|
||||||
|
struct spiffs_dirent *pe = &e;
|
||||||
|
if ((pe = SPIFFS_readdir(&_dir, pe))){
|
||||||
|
return FS.open((char *)pe->name);
|
||||||
|
}
|
||||||
|
return FSFile();
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t FSFile::size() {
|
uint32_t FSFile::size() {
|
||||||
if(! _file) return 0;
|
if(!_file) return 0;
|
||||||
|
if(_stats.size) return _stats.size;
|
||||||
uint32_t pos = SPIFFS_tell(&_filesystemStorageHandle, _file);
|
uint32_t pos = SPIFFS_tell(&_filesystemStorageHandle, _file);
|
||||||
SPIFFS_lseek(&_filesystemStorageHandle, _file, 0, SPIFFS_SEEK_END);
|
SPIFFS_lseek(&_filesystemStorageHandle, _file, 0, SPIFFS_SEEK_END);
|
||||||
uint32_t size = SPIFFS_tell(&_filesystemStorageHandle, _file);
|
_stats.size = SPIFFS_tell(&_filesystemStorageHandle, _file);
|
||||||
SPIFFS_lseek(&_filesystemStorageHandle, _file, pos, SPIFFS_SEEK_SET);
|
SPIFFS_lseek(&_filesystemStorageHandle, _file, pos, SPIFFS_SEEK_SET);
|
||||||
return size;
|
return _stats.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FSFile::available() {
|
||||||
|
if (!_file) return 0;
|
||||||
|
uint32_t pos = SPIFFS_tell(&_filesystemStorageHandle, _file);
|
||||||
|
return size() - pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t FSFile::seek(uint32_t pos) {
|
uint32_t FSFile::seek(uint32_t pos) {
|
||||||
if (! _file) return 0;
|
if (!_file) return 0;
|
||||||
return SPIFFS_lseek(&_filesystemStorageHandle, _file, pos, SPIFFS_SEEK_SET);
|
return SPIFFS_lseek(&_filesystemStorageHandle, _file, pos, SPIFFS_SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t FSFile::position() {
|
uint32_t FSFile::position() {
|
||||||
if (! _file) return 0;
|
if (!_file) return 0;
|
||||||
return SPIFFS_tell(&_filesystemStorageHandle, _file);
|
return SPIFFS_tell(&_filesystemStorageHandle, _file);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FSFile::eof() {
|
bool FSFile::eof() {
|
||||||
if (! _file) return 0;
|
if (!_file) return 0;
|
||||||
return SPIFFS_eof(&_filesystemStorageHandle, _file);
|
return SPIFFS_eof(&_filesystemStorageHandle, _file);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FSFile::isDirectory(void) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FSFile::read(void *buf, uint16_t nbyte) {
|
int FSFile::read(void *buf, uint16_t nbyte) {
|
||||||
if (! _file) return -1;
|
if (! _file || isDirectory()) return -1;
|
||||||
return SPIFFS_read(&_filesystemStorageHandle, _file, buf, nbyte);
|
return SPIFFS_read(&_filesystemStorageHandle, _file, buf, nbyte);
|
||||||
}
|
}
|
||||||
|
|
||||||
int FSFile::read() {
|
int FSFile::read() {
|
||||||
if (! _file) return -1;
|
if (! _file || isDirectory()) return -1;
|
||||||
int val;
|
int val;
|
||||||
if(SPIFFS_read(&_filesystemStorageHandle, _file, &val, 1) != 1) return -1;
|
if(SPIFFS_read(&_filesystemStorageHandle, _file, &val, 1) != 1) return -1;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FSFile::peek() {
|
int FSFile::peek() {
|
||||||
if (! _file) return 0;
|
if (! _file || isDirectory()) return 0;
|
||||||
int c = read();
|
int c = read();
|
||||||
SPIFFS_lseek(&_filesystemStorageHandle, _file, -1, SPIFFS_SEEK_CUR);
|
SPIFFS_lseek(&_filesystemStorageHandle, _file, -1, SPIFFS_SEEK_CUR);
|
||||||
return c;
|
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){
|
size_t FSFile::write(const uint8_t *buf, size_t size){
|
||||||
if (! _file) return 0;
|
if (! _file || isDirectory()) return 0;
|
||||||
int res = SPIFFS_write(&_filesystemStorageHandle, _file, (uint8_t *)buf, size);
|
int res = SPIFFS_write(&_filesystemStorageHandle, _file, (uint8_t *)buf, size);
|
||||||
return (res > 0)?(size_t)res:0;
|
return (res > 0)?(size_t)res:0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FSFile::write(uint8_t val) {
|
size_t FSFile::write(uint8_t val) {
|
||||||
if (! _file) return 0;
|
if (! _file || isDirectory()) return 0;
|
||||||
return write(&val, 1);
|
return write(&val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FSFile::flush(){
|
void FSFile::flush(){
|
||||||
if (! _file) return;
|
if (! _file || isDirectory()) return;
|
||||||
SPIFFS_fflush(&_filesystemStorageHandle, _file);
|
SPIFFS_fflush(&_filesystemStorageHandle, _file);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t FSFile::remove(){
|
bool FSFile::remove(){
|
||||||
if (! _file) return 0;
|
if (! _file) return 0;
|
||||||
return SPIFFS_fremove(&_filesystemStorageHandle, _file);
|
close();
|
||||||
_file = 0;
|
return SPIFFS_remove(&_filesystemStorageHandle, (char *)_stats.name) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FSFile::lastError(){
|
int FSFile::lastError(){
|
||||||
@ -187,28 +267,5 @@ int FSFile::lastError(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FSFile::clearError(){
|
void FSFile::clearError(){
|
||||||
_filesystemStorageHandle.errno = SPIFFS_OK;
|
_filesystemStorageHandle.err_code = SPIFFS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
char * FSFile::name(){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
spiffs_DIR *dirOpen(spiffs_DIR *d){
|
|
||||||
return SPIFFS_opendir(&_filesystemStorageHandle, 0, d);
|
|
||||||
}
|
|
||||||
|
|
||||||
int dirClose(spiffs_DIR *d){
|
|
||||||
return SPIFFS_closedir(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
file_t dirOpenFile(spiffs_dirent* entry, uint8_t flags){
|
|
||||||
return SPIFFS_open_by_dirent(&_filesystemStorageHandle, entry, (spiffs_flags)flags, 0);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
31
cores/esp8266/FileSystem.h
Executable file → Normal file
31
cores/esp8266/FileSystem.h
Executable file → Normal file
@ -26,14 +26,17 @@
|
|||||||
class String;
|
class String;
|
||||||
|
|
||||||
#define FSFILE_READ SPIFFS_RDONLY
|
#define FSFILE_READ SPIFFS_RDONLY
|
||||||
#define FSFILE_WRITE (SPIFFS_RDONLY | SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_TRUNC)
|
#define FSFILE_WRITE (SPIFFS_RDONLY | SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_APPEND )
|
||||||
|
#define FSFILE_OVERWRITE (SPIFFS_RDONLY | SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_TRUNC )
|
||||||
|
|
||||||
class FSFile : public Stream {
|
class FSFile : public Stream {
|
||||||
private:
|
private:
|
||||||
spiffs_stat _stats;
|
spiffs_stat _stats;
|
||||||
file_t _file;
|
file_t _file;
|
||||||
|
spiffs_DIR _dir;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
FSFile(String path);
|
||||||
FSFile(file_t f);
|
FSFile(file_t f);
|
||||||
FSFile(void);
|
FSFile(void);
|
||||||
virtual size_t write(uint8_t);
|
virtual size_t write(uint8_t);
|
||||||
@ -44,16 +47,18 @@ public:
|
|||||||
virtual void flush();
|
virtual void flush();
|
||||||
int read(void *buf, uint16_t nbyte);
|
int read(void *buf, uint16_t nbyte);
|
||||||
uint32_t seek(uint32_t pos);
|
uint32_t seek(uint32_t pos);
|
||||||
uint32_t remove();
|
|
||||||
uint32_t position();
|
uint32_t position();
|
||||||
uint32_t size();
|
uint32_t size();
|
||||||
bool eof();
|
bool eof();
|
||||||
void close();
|
void close();
|
||||||
|
bool remove();
|
||||||
int lastError();
|
int lastError();
|
||||||
void clearError();
|
void clearError();
|
||||||
operator bool() { return _file > 0; }
|
operator bool() { return _file > 0; }
|
||||||
char * name();
|
char * name();
|
||||||
bool isDirectory(void);
|
bool isDirectory(void);
|
||||||
|
void rewindDirectory(void);
|
||||||
|
FSFile openNextFile(void);
|
||||||
|
|
||||||
template<typename T> size_t write(T &src){
|
template<typename T> size_t write(T &src){
|
||||||
const size_t bufferSize = 64;
|
const size_t bufferSize = 64;
|
||||||
@ -80,18 +85,28 @@ public:
|
|||||||
class FSClass {
|
class FSClass {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _mounted = false;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool mount();
|
bool mount();
|
||||||
void unmount();
|
void unmount();
|
||||||
bool format();
|
bool format();
|
||||||
bool exists(const char *filename);
|
bool check();
|
||||||
bool create(const char *filepath);
|
bool exists(char *filename);
|
||||||
bool remove(const char *filepath);
|
bool create(char *filepath);
|
||||||
bool rename(const char *filename, const char *newname);
|
bool remove(char *filepath);
|
||||||
|
bool rename(char *filename, char *newname);
|
||||||
|
size_t totalBytes();
|
||||||
|
size_t usedBytes();
|
||||||
|
size_t size(){ return _filesystemStorageHandle.cfg.phys_size; }
|
||||||
|
size_t blockSize(){ return _filesystemStorageHandle.cfg.log_block_size; }
|
||||||
|
size_t totalBlocks(){ return _filesystemStorageHandle.block_count; }
|
||||||
|
size_t freeBlocks(){ return _filesystemStorageHandle.free_blocks; }
|
||||||
|
size_t pageSize(){ return _filesystemStorageHandle.cfg.log_page_size; }
|
||||||
|
size_t allocatedPages(){ return _filesystemStorageHandle.stats_p_allocated; }
|
||||||
|
size_t deletedPages(){ return _filesystemStorageHandle.stats_p_deleted; }
|
||||||
|
|
||||||
FSFile open(const char *filename, uint8_t mode = FSFILE_READ);
|
FSFile open(char *filename, uint8_t mode = FSFILE_READ);
|
||||||
|
FSFile open(spiffs_dirent* entry, uint8_t mode = FSFILE_READ);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class FSFile;
|
friend class FSFile;
|
||||||
|
@ -42,12 +42,12 @@ extern "C" {
|
|||||||
#define UART_TX_FIFO_SIZE 0x80
|
#define UART_TX_FIFO_SIZE 0x80
|
||||||
|
|
||||||
struct uart_ {
|
struct uart_ {
|
||||||
int uart_nr;
|
int uart_nr;
|
||||||
int baud_rate;
|
int baud_rate;
|
||||||
bool rxEnabled;
|
bool rxEnabled;
|
||||||
bool txEnabled;
|
bool txEnabled;
|
||||||
uint8_t rxPin;
|
uint8_t rxPin;
|
||||||
uint8_t txPin;
|
uint8_t txPin;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int UART0 = 0;
|
static const int UART0 = 0;
|
||||||
@ -120,7 +120,7 @@ void ICACHE_RAM_ATTR uart_interrupt_handler(uart_t* uart) {
|
|||||||
// -------------- UART 0 --------------
|
// -------------- UART 0 --------------
|
||||||
if(Serial.isRxEnabled()) {
|
if(Serial.isRxEnabled()) {
|
||||||
while(U0IS & (1 << UIFF)) {
|
while(U0IS & (1 << UIFF)) {
|
||||||
Serial._rx_complete_irq((char)(U0F & 0xff));
|
Serial._rx_complete_irq((char) (U0F & 0xff));
|
||||||
U0IC = (1 << UIFF);
|
U0IC = (1 << UIFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,7 +135,7 @@ void ICACHE_RAM_ATTR uart_interrupt_handler(uart_t* uart) {
|
|||||||
|
|
||||||
if(Serial1.isRxEnabled()) {
|
if(Serial1.isRxEnabled()) {
|
||||||
while(U1IS & (1 << UIFF)) {
|
while(U1IS & (1 << UIFF)) {
|
||||||
Serial1._rx_complete_irq((char)(U1F & 0xff));
|
Serial1._rx_complete_irq((char) (U1F & 0xff));
|
||||||
U1IC = (1 << UIFF);
|
U1IC = (1 << UIFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -357,19 +357,19 @@ void uart_swap(uart_t* uart) {
|
|||||||
switch(uart->uart_nr) {
|
switch(uart->uart_nr) {
|
||||||
case UART0:
|
case UART0:
|
||||||
if(uart->txPin == 1 && uart->rxPin == 3) {
|
if(uart->txPin == 1 && uart->rxPin == 3) {
|
||||||
pinMode(15, FUNCTION_4);//TX
|
pinMode(15, FUNCTION_4); //TX
|
||||||
pinMode(13, FUNCTION_4);//RX
|
pinMode(13, FUNCTION_4); //RX
|
||||||
USWAP |= (1 << USWAP0);
|
USWAP |= (1 << USWAP0);
|
||||||
pinMode(1, INPUT);//TX
|
pinMode(1, INPUT); //TX
|
||||||
pinMode(3, INPUT);//RX
|
pinMode(3, INPUT); //RX
|
||||||
uart->rxPin = 13;
|
uart->rxPin = 13;
|
||||||
uart->txPin = 15;
|
uart->txPin = 15;
|
||||||
} else {
|
} else {
|
||||||
pinMode(1, SPECIAL);//TX
|
pinMode(1, SPECIAL); //TX
|
||||||
pinMode(3, SPECIAL);//RX
|
pinMode(3, SPECIAL); //RX
|
||||||
USWAP &= ~(1 << USWAP0);
|
USWAP &= ~(1 << USWAP0);
|
||||||
pinMode(15, INPUT);//TX
|
pinMode(15, INPUT); //TX
|
||||||
pinMode(13, INPUT);//RX
|
pinMode(13, INPUT); //RX
|
||||||
uart->rxPin = 3;
|
uart->rxPin = 3;
|
||||||
uart->txPin = 1;
|
uart->txPin = 1;
|
||||||
}
|
}
|
||||||
@ -392,30 +392,50 @@ void uart_ignore_char(char c) {
|
|||||||
|
|
||||||
void uart0_write_char(char c) {
|
void uart0_write_char(char c) {
|
||||||
if(&Serial != NULL && Serial.isTxEnabled()) {
|
if(&Serial != NULL && Serial.isTxEnabled()) {
|
||||||
if(c == '\n') {
|
if(Serial.availableForWrite() > 0) {
|
||||||
Serial.write('\r');
|
if(c == '\n') {
|
||||||
|
Serial.write('\r');
|
||||||
|
}
|
||||||
|
Serial.write(c);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
Serial.write(c);
|
|
||||||
} else {
|
|
||||||
if(c == '\n') {
|
|
||||||
USF(0) = '\r';
|
|
||||||
}
|
|
||||||
USF(0) = c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wait for the Hardware FIFO
|
||||||
|
while(true) {
|
||||||
|
if(((USS(0) >> USTXC) & 0xff) <= (UART_TX_FIFO_SIZE - 2)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(c == '\n') {
|
||||||
|
USF(0) = '\r';
|
||||||
|
}
|
||||||
|
USF(0) = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart1_write_char(char c) {
|
void uart1_write_char(char c) {
|
||||||
if(&Serial1 != NULL && Serial1.isTxEnabled()) {
|
if(&Serial1 != NULL && Serial1.isTxEnabled()) {
|
||||||
if(c == '\n') {
|
if(Serial1.availableForWrite() > 0) {
|
||||||
Serial1.write('\r');
|
if(c == '\n') {
|
||||||
|
Serial1.write('\r');
|
||||||
|
}
|
||||||
|
Serial1.write(c);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
Serial1.write(c);
|
|
||||||
} else {
|
|
||||||
if(c == '\n') {
|
|
||||||
USF(1) = '\r';
|
|
||||||
}
|
|
||||||
USF(1) = c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wait for the Hardware FIFO
|
||||||
|
while(true) {
|
||||||
|
if(((USS(1) >> USTXC) & 0xff) <= (UART_TX_FIFO_SIZE - 2)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(c == '\n') {
|
||||||
|
USF(1) = '\r';
|
||||||
|
}
|
||||||
|
USF(1) = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s_uart_debug_nr = UART0;
|
static int s_uart_debug_nr = UART0;
|
||||||
@ -465,11 +485,11 @@ void HardwareSerial::begin(unsigned long baud, byte config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(_uart->rxEnabled) {
|
if(_uart->rxEnabled) {
|
||||||
if (!_rx_buffer)
|
if(!_rx_buffer)
|
||||||
_rx_buffer = new cbuf(SERIAL_RX_BUFFER_SIZE);
|
_rx_buffer = new cbuf(SERIAL_RX_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
if(_uart->txEnabled) {
|
if(_uart->txEnabled) {
|
||||||
if (!_tx_buffer)
|
if(!_tx_buffer)
|
||||||
_tx_buffer = new cbuf(SERIAL_TX_BUFFER_SIZE);
|
_tx_buffer = new cbuf(SERIAL_TX_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
_written = false;
|
_written = false;
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "Print.h"
|
#include "Print.h"
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "c_types.h"
|
#include "c_types.h"
|
||||||
|
#include "ets_sys.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public Methods //////////////////////////////////////////////////////////////
|
// Public Methods //////////////////////////////////////////////////////////////
|
||||||
@ -43,6 +44,16 @@ size_t ICACHE_FLASH_ATTR Print::write(const uint8_t *buffer, size_t size) {
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t Print::printf(const char *format, ...) {
|
||||||
|
va_list arg;
|
||||||
|
va_start(arg, format);
|
||||||
|
char temp[256];
|
||||||
|
size_t len = ets_vsnprintf(temp, 256, format, arg);
|
||||||
|
len = print(temp);
|
||||||
|
va_end(arg);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
size_t ICACHE_FLASH_ATTR Print::print(const __FlashStringHelper *ifsh) {
|
size_t ICACHE_FLASH_ATTR Print::print(const __FlashStringHelper *ifsh) {
|
||||||
PGM_P p = reinterpret_cast<PGM_P>(ifsh);
|
PGM_P p = reinterpret_cast<PGM_P>(ifsh);
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@ class Print {
|
|||||||
return write((const uint8_t *) buffer, size);
|
return write((const uint8_t *) buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t printf(const char * format, ...);
|
||||||
size_t print(const __FlashStringHelper *);
|
size_t print(const __FlashStringHelper *);
|
||||||
size_t print(const String &);
|
size_t print(const String &);
|
||||||
size_t print(const char[]);
|
size_t print(const char[]);
|
||||||
|
@ -26,10 +26,12 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *operator new(size_t size) {
|
void *operator new(size_t size) {
|
||||||
|
size = ((size + 3) & ~((size_t)0x3));
|
||||||
return os_malloc(size);
|
return os_malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *operator new[](size_t size) {
|
void *operator new[](size_t size) {
|
||||||
|
size = ((size + 3) & ~((size_t)0x3));
|
||||||
return os_malloc(size);
|
return os_malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,10 +188,10 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) {
|
|||||||
++out;
|
++out;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(prec-- > 0) {
|
for (unsigned char decShift = prec; decShift > 0; decShift--) {
|
||||||
remainder *= 10.0;
|
remainder *= 10.0;
|
||||||
}
|
}
|
||||||
sprintf(out, "%d", (int) remainder);
|
sprintf(out, "%0*d", prec, (int)remainder);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include "user_interface.h"
|
#include "user_interface.h"
|
||||||
|
|
||||||
void* malloc(size_t size) {
|
void* malloc(size_t size) {
|
||||||
|
size = ((size + 3) & ~((size_t)0x3));
|
||||||
return os_malloc(size);
|
return os_malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,6 +47,7 @@ void free(void* ptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* realloc(void* ptr, size_t size) {
|
void* realloc(void* ptr, size_t size) {
|
||||||
|
size = ((size + 3) & ~((size_t)0x3));
|
||||||
return os_realloc(ptr, size);
|
return os_realloc(ptr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
cores/esp8266/spiffs/docs/INTEGRATION → cores/esp8266/spiffs/INTEGRATION
Executable file → Normal file
2
cores/esp8266/spiffs/docs/INTEGRATION → cores/esp8266/spiffs/INTEGRATION
Executable file → Normal file
@ -303,4 +303,4 @@ Having these figures you can disable SPIFFS_BUFFER_HELP again to save flash.
|
|||||||
|
|
||||||
* HOW TO CONFIG
|
* HOW TO CONFIG
|
||||||
|
|
||||||
TODO
|
TODO
|
@ -1,44 +0,0 @@
|
|||||||
|
|
||||||
#############################################################
|
|
||||||
# Required variables for each makefile
|
|
||||||
# Discard this section from all parent makefiles
|
|
||||||
# Expected variables (with automatic defaults):
|
|
||||||
# CSRCS (all "C" files in the dir)
|
|
||||||
# SUBDIRS (all subdirs with a Makefile)
|
|
||||||
# GEN_LIBS - list of libs to be generated ()
|
|
||||||
# GEN_IMAGES - list of images to be generated ()
|
|
||||||
# COMPONENTS_xxx - a list of libs/objs in the form
|
|
||||||
# subdir/lib to be extracted and rolled up into
|
|
||||||
# a generated lib/image xxx.a ()
|
|
||||||
#
|
|
||||||
ifndef PDIR
|
|
||||||
GEN_LIBS = spiffs.a
|
|
||||||
endif
|
|
||||||
|
|
||||||
#############################################################
|
|
||||||
# Configuration i.e. compile options etc.
|
|
||||||
# Target specific stuff (defines etc.) goes in here!
|
|
||||||
# Generally values applying to a tree are captured in the
|
|
||||||
# makefile at its root level - these are then overridden
|
|
||||||
# for a subtree within the makefile rooted therein
|
|
||||||
#
|
|
||||||
#DEFINES +=
|
|
||||||
|
|
||||||
#############################################################
|
|
||||||
# Recursion Magic - Don't touch this!!
|
|
||||||
#
|
|
||||||
# Each subtree potentially has an include directory
|
|
||||||
# corresponding to the common APIs applicable to modules
|
|
||||||
# rooted at that subtree. Accordingly, the INCLUDE PATH
|
|
||||||
# of a module can only contain the include directories up
|
|
||||||
# its parent path, and not its siblings
|
|
||||||
#
|
|
||||||
# Required for each makefile to inherit from the parent
|
|
||||||
#
|
|
||||||
|
|
||||||
INCLUDES := $(INCLUDES) -I $(PDIR)include
|
|
||||||
INCLUDES += -I ./
|
|
||||||
INCLUDES += -I ../libc
|
|
||||||
INCLUDES += -I ../platform
|
|
||||||
PDIR := ../$(PDIR)
|
|
||||||
sinclude $(PDIR)Makefile
|
|
86
cores/esp8266/spiffs/README
Normal file
86
cores/esp8266/spiffs/README
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
SPIFFS (SPI Flash File System)
|
||||||
|
V0.3.0
|
||||||
|
|
||||||
|
Copyright (c) 2013-2015 Peter Andersson (pelleplutt1976<at>gmail.com)
|
||||||
|
|
||||||
|
For legal stuff, see LICENCE in this directory. Basically, you may do whatever
|
||||||
|
you want with the source. Use, modify, sell, print it out, roll it and smoke it
|
||||||
|
- as long as I won't be held responsible.
|
||||||
|
|
||||||
|
Love to hear feedback though!
|
||||||
|
|
||||||
|
|
||||||
|
* INTRODUCTION
|
||||||
|
|
||||||
|
Spiffs is a file system intended for SPI NOR flash devices on embedded targets.
|
||||||
|
|
||||||
|
Spiffs is designed with following characteristics in mind:
|
||||||
|
- Small (embedded) targets, sparse RAM without heap
|
||||||
|
- Only big areas of data (blocks) can be erased
|
||||||
|
- An erase will reset all bits in block to ones
|
||||||
|
- Writing pulls one to zeroes
|
||||||
|
- Zeroes can only be pulled to ones by erase
|
||||||
|
- Wear leveling
|
||||||
|
|
||||||
|
|
||||||
|
* FEATURES
|
||||||
|
|
||||||
|
What spiffs does:
|
||||||
|
- Specifically designed for low ram usage
|
||||||
|
- Uses statically sized ram buffers, independent of number of files
|
||||||
|
- Posix-like api: open, close, read, write, seek, stat, etc
|
||||||
|
- It can be run on any NOR flash, not only SPI flash - theoretically also on
|
||||||
|
embedded flash of an microprocessor
|
||||||
|
- Multiple spiffs configurations can be run on same target - and even on same
|
||||||
|
SPI flash device
|
||||||
|
- Implements static wear leveling
|
||||||
|
- Built in file system consistency checks
|
||||||
|
|
||||||
|
What spiffs does not:
|
||||||
|
- Presently, spiffs does not support directories. It produces a flat
|
||||||
|
structure. Creating a file with path "tmp/myfile.txt" will create a file
|
||||||
|
called "tmp/myfile.txt" instead of a "myfile.txt" under directory "tmp".
|
||||||
|
- It is not a realtime stack. One write operation might take much longer than
|
||||||
|
another.
|
||||||
|
- Poor scalability. Spiffs is intended for small memory devices - the normal
|
||||||
|
sizes for SPI flashes. Going beyond ~128MB is probably a bad idea. This is
|
||||||
|
a side effect of the design goal to use as little ram as possible.
|
||||||
|
- Presently, it does not detect or handle bad blocks.
|
||||||
|
|
||||||
|
|
||||||
|
* MORE INFO
|
||||||
|
|
||||||
|
For integration, see the docs/INTEGRATION file.
|
||||||
|
|
||||||
|
For use and design, see the docs/TECH_SPEC file.
|
||||||
|
|
||||||
|
For testing and contributions, see the docs/IMPLEMENTING file.
|
||||||
|
|
||||||
|
* HISTORY
|
||||||
|
|
||||||
|
0.3.0
|
||||||
|
Added existing namecheck when creating files
|
||||||
|
Lots of static analysis bugs #6
|
||||||
|
Added rename func
|
||||||
|
Fix SPIFFS_read length when reading beyond file size
|
||||||
|
Added reading beyond file length testcase
|
||||||
|
Made build a bit more configurable
|
||||||
|
Changed name in spiffs from "errno" to "err_code" due to conflicts compiling
|
||||||
|
in mingw
|
||||||
|
Improved GC checks, fixed an append bug, more robust truncate for very special
|
||||||
|
case
|
||||||
|
GC checks preempts GC, truncate even less picky
|
||||||
|
Struct alignment needed for some targets, define in spiffs config #10
|
||||||
|
Spiffs filesystem magic, definable in config
|
||||||
|
|
||||||
|
New config defines:
|
||||||
|
SPIFFS_USE_MAGIC - enable or disable magic check upon mount
|
||||||
|
SPIFFS_ALIGNED_OBJECT_INDEX_TABLES - alignment for certain targets
|
||||||
|
New API functions:
|
||||||
|
SPIFFS_rename - rename files
|
||||||
|
SPIFFS_clearerr - clears last errno
|
||||||
|
SPIFFS_info - returns info on used and total bytes in fs
|
||||||
|
SPIFFS_format - formats the filesystem
|
||||||
|
SPIFFS_mounted - checks if filesystem is mounted
|
||||||
|
|
||||||
|
|
0
cores/esp8266/spiffs/docs/TECH_SPEC → cores/esp8266/spiffs/TECH_SPEC
Executable file → Normal file
0
cores/esp8266/spiffs/docs/TECH_SPEC → cores/esp8266/spiffs/TECH_SPEC
Executable file → Normal file
15
cores/esp8266/spiffs/TODO
Normal file
15
cores/esp8266/spiffs/TODO
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
* When mending lost pages, also see if they fit into length specified in object index header
|
||||||
|
|
||||||
|
SPIFFS2 thoughts
|
||||||
|
|
||||||
|
* Instead of exact object id:s in the object lookup tables, use a hash of span index and object id.
|
||||||
|
Eg. object id xor:ed with bit-reversed span index.
|
||||||
|
This should decrease number of actual pages that needs to be visited when looking thru the obj lut.
|
||||||
|
|
||||||
|
* Logical number of each block. When moving stuff in a garbage collected page, the free
|
||||||
|
page is assigned the same number as the garbage collected. Thus, object index pages do not have to
|
||||||
|
be rewritten.
|
||||||
|
|
||||||
|
* Steal one page, use as a bit parity page. When starting an fs modification operation, write one bit
|
||||||
|
as zero. When ending, write another bit as zero. On mount, if number of zeroes in page is uneven, a
|
||||||
|
check is automatically run.
|
@ -1 +0,0 @@
|
|||||||
* When mending lost pages, also see if they fit into length specified in object index header
|
|
@ -1,73 +0,0 @@
|
|||||||
// Based on NodeMCU platform_flash
|
|
||||||
// https://github.com/nodemcu/nodemcu-firmware
|
|
||||||
|
|
||||||
#ifndef SYSTEM_FLASHMEM_H_
|
|
||||||
#define SYSTEM_FLASHMEM_H_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "spiffs.h"
|
|
||||||
#include "spi_flash.h"
|
|
||||||
|
|
||||||
#define INTERNAL_FLASH_WRITE_UNIT_SIZE 4
|
|
||||||
#define INTERNAL_FLASH_READ_UNIT_SIZE 4
|
|
||||||
|
|
||||||
#define FLASH_TOTAL_SEC_COUNT (flashmem_get_size_sectors())
|
|
||||||
|
|
||||||
#define SYS_PARAM_SEC_COUNT 4
|
|
||||||
#define FLASH_WORK_SEC_COUNT (FLASH_TOTAL_SEC_COUNT - SYS_PARAM_SEC_COUNT)
|
|
||||||
|
|
||||||
#define INTERNAL_FLASH_SECTOR_SIZE SPI_FLASH_SEC_SIZE
|
|
||||||
#define INTERNAL_FLASH_SIZE ( (FLASH_WORK_SEC_COUNT) * INTERNAL_FLASH_SECTOR_SIZE )
|
|
||||||
#define INTERNAL_FLASH_START_ADDRESS 0x40200000
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint8_t unknown0;
|
|
||||||
uint8_t unknown1;
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
MODE_QIO = 0,
|
|
||||||
MODE_QOUT = 1,
|
|
||||||
MODE_DIO = 2,
|
|
||||||
MODE_DOUT = 15,
|
|
||||||
} mode : 8;
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
SPEED_40MHZ = 0,
|
|
||||||
SPEED_26MHZ = 1,
|
|
||||||
SPEED_20MHZ = 2,
|
|
||||||
SPEED_80MHZ = 15,
|
|
||||||
} speed : 4;
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
SIZE_4MBIT = 0,
|
|
||||||
SIZE_2MBIT = 1,
|
|
||||||
SIZE_8MBIT = 2,
|
|
||||||
SIZE_16MBIT = 3,
|
|
||||||
SIZE_32MBIT = 4,
|
|
||||||
} size : 4;
|
|
||||||
} STORE_TYPEDEF_ATTR SPIFlashInfo;
|
|
||||||
|
|
||||||
extern uint32_t flashmem_write( const void *from, uint32_t toaddr, uint32_t size );
|
|
||||||
extern uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size );
|
|
||||||
extern bool flashmem_erase_sector( uint32_t sector_id );
|
|
||||||
|
|
||||||
extern SPIFlashInfo flashmem_get_info();
|
|
||||||
extern uint8_t flashmem_get_size_type();
|
|
||||||
extern uint32_t flashmem_get_size_bytes();
|
|
||||||
extern uint16_t flashmem_get_size_sectors();
|
|
||||||
uint32_t flashmem_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend );
|
|
||||||
uint32_t flashmem_get_sector_of_address( uint32_t addr );
|
|
||||||
|
|
||||||
extern uint32_t flashmem_write_internal( const void *from, uint32_t toaddr, uint32_t size );
|
|
||||||
extern uint32_t flashmem_read_internal( void *to, uint32_t fromaddr, uint32_t size );
|
|
||||||
extern uint32_t flashmem_get_first_free_block_address();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* SYSTEM_FLASHMEM_H_ */
|
|
@ -1,146 +0,0 @@
|
|||||||
#include "spiffs.h"
|
|
||||||
|
|
||||||
#define LOG_PAGE_SIZE 256
|
|
||||||
|
|
||||||
spiffs _filesystemStorageHandle;
|
|
||||||
|
|
||||||
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){
|
|
||||||
flashmem_read(dst, addr, size);
|
|
||||||
return SPIFFS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
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){
|
|
||||||
debugf("api_spiffs_erase");
|
|
||||||
u32_t sect_first = flashmem_get_sector_of_address(addr);
|
|
||||||
u32_t sect_last = sect_first;
|
|
||||||
while( sect_first <= sect_last )
|
|
||||||
if( !flashmem_erase_sector( sect_first ++ ) )
|
|
||||||
return SPIFFS_ERR_INTERNAL;
|
|
||||||
return SPIFFS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************
|
|
||||||
The W25Q32BV array is organized into 16,384 programmable pages of 256-bytes each. Up to 256 bytes can be programmed at a time.
|
|
||||||
Pages can be erased in groups of 16 (4KB sector erase), groups of 128 (32KB block erase), groups of 256 (64KB block erase) or
|
|
||||||
the entire chip (chip erase). The W25Q32BV has 1,024 erasable sectors and 64 erasable blocks respectively.
|
|
||||||
The small 4KB sectors allow for greater flexibility in applications that require data and parameter storage.
|
|
||||||
********************/
|
|
||||||
|
|
||||||
extern uint32_t _SPIFFS_start;
|
|
||||||
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;
|
|
||||||
cfg.phys_size = (u32_t)((u32_t)&_SPIFFS_end - (u32_t)&_SPIFFS_start);
|
|
||||||
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(){
|
|
||||||
spiffs_config cfg = spiffs_get_storage_config();
|
|
||||||
if (cfg.phys_addr == 0){
|
|
||||||
SYSTEM_ERROR("Can't format file system, wrong address");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32_t sect_first, sect_last;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 false;
|
|
||||||
}
|
|
||||||
|
|
||||||
debugf("fs.start:%x, size:%d Kb\n", cfg.phys_addr, cfg.phys_size / 1024);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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,
|
|
||||||
&cfg,
|
|
||||||
spiffs_work_buf,
|
|
||||||
spiffs_fds,
|
|
||||||
sizeof(spiffs_fds),
|
|
||||||
spiffs_cache,
|
|
||||||
sizeof(spiffs_cache),
|
|
||||||
NULL);
|
|
||||||
debugf("mount res: %d\n", res);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spiffs_unmount(){
|
|
||||||
SPIFFS_unmount(&_filesystemStorageHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool spiffs_format(){
|
|
||||||
spiffs_unmount();
|
|
||||||
if(!spiffs_format_internal()) return false;
|
|
||||||
spiffs_mount();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_spiffs(){
|
|
||||||
char buf[12] = {0};
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
112
cores/esp8266/spiffs/spiffs.h
Executable file → Normal file
112
cores/esp8266/spiffs/spiffs.h
Executable file → Normal file
@ -5,15 +5,15 @@
|
|||||||
* Author: petera
|
* Author: petera
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef SPIFFS_H_
|
#ifndef SPIFFS_H_
|
||||||
#define SPIFFS_H_
|
#define SPIFFS_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "spiffs_config.h"
|
#include "spiffs_config.h"
|
||||||
#include "flashmem.h"
|
|
||||||
|
|
||||||
#define SPIFFS_OK 0
|
#define SPIFFS_OK 0
|
||||||
#define SPIFFS_ERR_NOT_MOUNTED -10000
|
#define SPIFFS_ERR_NOT_MOUNTED -10000
|
||||||
@ -40,6 +40,13 @@ extern "C" {
|
|||||||
#define SPIFFS_ERR_NOT_WRITABLE -10021
|
#define SPIFFS_ERR_NOT_WRITABLE -10021
|
||||||
#define SPIFFS_ERR_NOT_READABLE -10022
|
#define SPIFFS_ERR_NOT_READABLE -10022
|
||||||
#define SPIFFS_ERR_CONFLICTING_NAME -10023
|
#define SPIFFS_ERR_CONFLICTING_NAME -10023
|
||||||
|
#define SPIFFS_ERR_NOT_CONFIGURED -10024
|
||||||
|
|
||||||
|
#define SPIFFS_ERR_NOT_A_FS -10025
|
||||||
|
#define SPIFFS_ERR_MOUNTED -10026
|
||||||
|
#define SPIFFS_ERR_ERASE_FAIL -10027
|
||||||
|
#define SPIFFS_ERR_MAGIC_NOT_POSSIBLE -10028
|
||||||
|
|
||||||
|
|
||||||
#define SPIFFS_ERR_INTERNAL -10050
|
#define SPIFFS_ERR_INTERNAL -10050
|
||||||
|
|
||||||
@ -81,19 +88,21 @@ typedef enum {
|
|||||||
} spiffs_check_report;
|
} spiffs_check_report;
|
||||||
|
|
||||||
/* file system check callback function */
|
/* 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
|
#ifndef SPIFFS_DBG
|
||||||
#define SPIFFS_DBG(...) printf(__VA_ARGS__)
|
#define SPIFFS_DBG(...) \
|
||||||
|
print(__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
#ifndef SPIFFS_GC_DBG
|
#ifndef SPIFFS_GC_DBG
|
||||||
#define SPIFFS_GC_DBG(...) printf(__VA_ARGS__)
|
#define SPIFFS_GC_DBG(...) c_printf(__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
#ifndef SPIFFS_CACHE_DBG
|
#ifndef SPIFFS_CACHE_DBG
|
||||||
#define SPIFFS_CACHE_DBG(...) printf(__VA_ARGS__)
|
#define SPIFFS_CACHE_DBG(...) c_printf(__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
#ifndef SPIFFS_CHECK_DBG
|
#ifndef SPIFFS_CHECK_DBG
|
||||||
#define SPIFFS_CHECK_DBG(...) printf(__VA_ARGS__)
|
#define SPIFFS_CHECK_DBG(...) c_printf(__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Any write to the filehandle is appended to end of the file */
|
/* Any write to the filehandle is appended to end of the file */
|
||||||
@ -182,7 +191,7 @@ typedef struct {
|
|||||||
u32_t fd_count;
|
u32_t fd_count;
|
||||||
|
|
||||||
// last error
|
// last error
|
||||||
s32_t errno;
|
s32_t err_code;
|
||||||
|
|
||||||
// current number of free blocks
|
// current number of free blocks
|
||||||
u32_t free_blocks;
|
u32_t free_blocks;
|
||||||
@ -212,6 +221,11 @@ typedef struct {
|
|||||||
|
|
||||||
// check callback function
|
// check callback function
|
||||||
spiffs_check_callback check_cb_f;
|
spiffs_check_callback check_cb_f;
|
||||||
|
|
||||||
|
// mounted flag
|
||||||
|
u8_t mounted;
|
||||||
|
// config magic
|
||||||
|
u32_t config_magic;
|
||||||
} spiffs;
|
} spiffs;
|
||||||
|
|
||||||
/* spiffs file status struct */
|
/* spiffs file status struct */
|
||||||
@ -239,7 +253,10 @@ typedef struct {
|
|||||||
// functions
|
// functions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the file system dynamic parameters and mounts the filesystem
|
* Initializes the file system dynamic parameters and mounts the filesystem.
|
||||||
|
* If SPIFFS_USE_MAGIC is enabled the mounting may fail with SPIFFS_ERR_NOT_A_FS
|
||||||
|
* if the flash does not contain a recognizable file system.
|
||||||
|
* In this case, SPIFFS_format must be called prior to remounting.
|
||||||
* @param fs the file system struct
|
* @param fs the file system struct
|
||||||
* @param config the physical and logical configuration of the file system
|
* @param config the physical and logical configuration of the file system
|
||||||
* @param work a memory work buffer comprising 2*config->log_page_size
|
* @param work a memory work buffer comprising 2*config->log_page_size
|
||||||
@ -268,7 +285,7 @@ void SPIFFS_unmount(spiffs *fs);
|
|||||||
* @param path the path of the new file
|
* @param path the path of the new file
|
||||||
* @param mode ignored, for posix compliance
|
* @param mode ignored, for posix compliance
|
||||||
*/
|
*/
|
||||||
s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode);
|
s32_t SPIFFS_creat(spiffs *fs, char *path, spiffs_mode mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens/creates a file.
|
* Opens/creates a file.
|
||||||
@ -279,7 +296,8 @@ s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode);
|
|||||||
* SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT
|
* SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT
|
||||||
* @param mode ignored, for posix compliance
|
* @param mode ignored, for posix compliance
|
||||||
*/
|
*/
|
||||||
spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode mode);
|
spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode mode);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a file by given dir entry.
|
* Opens a file by given dir entry.
|
||||||
@ -304,7 +322,7 @@ spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_fl
|
|||||||
* @param len how much to read
|
* @param len how much to read
|
||||||
* @returns number of bytes read, or -1 if error
|
* @returns number of bytes read, or -1 if error
|
||||||
*/
|
*/
|
||||||
s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, u32_t len);
|
s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes to given filehandle.
|
* Writes to given filehandle.
|
||||||
@ -314,7 +332,7 @@ s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, u32_t len);
|
|||||||
* @param len how much to write
|
* @param len how much to write
|
||||||
* @returns number of bytes written, or -1 if error
|
* @returns number of bytes written, or -1 if error
|
||||||
*/
|
*/
|
||||||
s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len);
|
s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves the read/write file offset
|
* Moves the read/write file offset
|
||||||
@ -332,7 +350,7 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence);
|
|||||||
* @param fs the file system struct
|
* @param fs the file system struct
|
||||||
* @param path the path of the file to remove
|
* @param path the path of the file to remove
|
||||||
*/
|
*/
|
||||||
s32_t SPIFFS_remove(spiffs *fs, const char *path);
|
s32_t SPIFFS_remove(spiffs *fs, char *path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a file by filehandle
|
* Removes a file by filehandle
|
||||||
@ -347,7 +365,7 @@ s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh);
|
|||||||
* @param path the path of the file to stat
|
* @param path the path of the file to stat
|
||||||
* @param s the stat struct to populate
|
* @param s the stat struct to populate
|
||||||
*/
|
*/
|
||||||
s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s);
|
s32_t SPIFFS_stat(spiffs *fs, char *path, spiffs_stat *s);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets file status by filehandle
|
* Gets file status by filehandle
|
||||||
@ -375,9 +393,9 @@ void SPIFFS_close(spiffs *fs, spiffs_file fh);
|
|||||||
* Renames a file
|
* Renames a file
|
||||||
* @param fs the file system struct
|
* @param fs the file system struct
|
||||||
* @param old path of file to rename
|
* @param old path of file to rename
|
||||||
* @param new new path of file
|
* @param newPath new path of file
|
||||||
*/
|
*/
|
||||||
s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newname);
|
s32_t SPIFFS_rename(spiffs *fs, char *old, char *newPath);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns last error of last file operation.
|
* Returns last error of last file operation.
|
||||||
@ -385,6 +403,12 @@ s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newname);
|
|||||||
*/
|
*/
|
||||||
s32_t SPIFFS_errno(spiffs *fs);
|
s32_t SPIFFS_errno(spiffs *fs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears last error.
|
||||||
|
* @param fs the file system struct
|
||||||
|
*/
|
||||||
|
void SPIFFS_clearerr(spiffs *fs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a directory stream corresponding to the given name.
|
* Opens a directory stream corresponding to the given name.
|
||||||
* The stream is positioned at the first entry in the directory.
|
* The stream is positioned at the first entry in the directory.
|
||||||
@ -394,7 +418,7 @@ s32_t SPIFFS_errno(spiffs *fs);
|
|||||||
* @param name the name of the directory
|
* @param name the name of the directory
|
||||||
* @param d pointer the directory stream to be populated
|
* @param d pointer the directory stream to be populated
|
||||||
*/
|
*/
|
||||||
spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d);
|
spiffs_DIR *SPIFFS_opendir(spiffs *fs, char *name, spiffs_DIR *d);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes a directory stream
|
* Closes a directory stream
|
||||||
@ -416,12 +440,51 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e);
|
|||||||
*/
|
*/
|
||||||
s32_t SPIFFS_check(spiffs *fs);
|
s32_t SPIFFS_check(spiffs *fs);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns number of total bytes available and number of used bytes.
|
||||||
|
* This is an estimation, and depends on if there a many files with little
|
||||||
|
* data or few files with much data.
|
||||||
|
* NB: If used number of bytes exceeds total bytes, a SPIFFS_check should
|
||||||
|
* run. This indicates a power loss in midst of things. In worst case
|
||||||
|
* (repeated powerlosses in mending or gc) you might have to delete some files.
|
||||||
|
*
|
||||||
|
* @param fs the file system struct
|
||||||
|
* @param total total number of bytes in filesystem
|
||||||
|
* @param used used number of bytes in filesystem
|
||||||
|
*/
|
||||||
|
s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the entire file system. All data will be lost.
|
||||||
|
* The filesystem must not be mounted when calling this.
|
||||||
|
*
|
||||||
|
* NB: formatting is awkward. Due to backwards compatibility, SPIFFS_mount
|
||||||
|
* MUST be called prior to formatting in order to configure the filesystem.
|
||||||
|
* If SPIFFS_mount succeeds, SPIFFS_unmount must be called before calling
|
||||||
|
* SPIFFS_format.
|
||||||
|
* If SPIFFS_mount fails, SPIFFS_format can be called directly without calling
|
||||||
|
* SPIFFS_unmount first.
|
||||||
|
*/
|
||||||
|
s32_t SPIFFS_format(spiffs *fs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns nonzero if spiffs is mounted, or zero if unmounted.
|
||||||
|
*/
|
||||||
|
u8_t SPIFFS_mounted(spiffs *fs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if EOF reached.
|
* Check if EOF reached.
|
||||||
* @param fs the file system struct
|
* @param fs the file system struct
|
||||||
* @param fh the filehandle of the file to check
|
* @param fh the filehandle of the file to check
|
||||||
*/
|
*/
|
||||||
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh);
|
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current position of the data pointer.
|
||||||
|
* @param fs the file system struct
|
||||||
|
* @param fh the filehandle of the open file
|
||||||
|
*/
|
||||||
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh);
|
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh);
|
||||||
|
|
||||||
#if SPIFFS_TEST_VISUALISATION
|
#if SPIFFS_TEST_VISUALISATION
|
||||||
@ -448,19 +511,10 @@ u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages);
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SPIFFS_CACHE
|
#include "spiffs_esp8266.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
bool spiffs_mount();
|
|
||||||
void spiffs_unmount();
|
|
||||||
bool spiffs_format();
|
|
||||||
spiffs_config spiffs_get_storage_config();
|
|
||||||
extern void test_spiffs();
|
|
||||||
|
|
||||||
extern spiffs _filesystemStorageHandle;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* SPIFFS_H_ */
|
#endif /* SPIFFS_H_ */
|
||||||
|
0
cores/esp8266/spiffs/spiffs_cache.c
Executable file → Normal file
0
cores/esp8266/spiffs/spiffs_cache.c
Executable file → Normal file
4
cores/esp8266/spiffs/spiffs_check.c
Executable file → Normal file
4
cores/esp8266/spiffs/spiffs_check.c
Executable file → Normal file
@ -597,7 +597,7 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
|||||||
data_spix_offset + i, data_pix, cur_pix);
|
data_spix_offset + i, data_pix, cur_pix);
|
||||||
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
|
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
|
||||||
// index bad also, cannot mend this file
|
// index bad also, cannot mend this file
|
||||||
SPIFFS_CHECK_DBG("PA: FIXUP: index bad %u, cannot mend - delete object\n", res);
|
SPIFFS_CHECK_DBG("PA: FIXUP: index bad %d, cannot mend - delete object\n", res);
|
||||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, objix_p_hdr->obj_id, 0);
|
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, objix_p_hdr->obj_id, 0);
|
||||||
// delete file
|
// delete file
|
||||||
res = spiffs_page_delete(fs, cur_pix);
|
res = spiffs_page_delete(fs, cur_pix);
|
||||||
@ -763,7 +763,7 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
|||||||
res = spiffs_rewrite_index(fs, p_hdr.obj_id, p_hdr.span_ix, cur_pix, objix_pix);
|
res = spiffs_rewrite_index(fs, p_hdr.obj_id, p_hdr.span_ix, cur_pix, objix_pix);
|
||||||
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
|
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
|
||||||
// index bad also, cannot mend this file
|
// index bad also, cannot mend this file
|
||||||
SPIFFS_CHECK_DBG("PA: FIXUP: index bad %u, cannot mend!\n", res);
|
SPIFFS_CHECK_DBG("PA: FIXUP: index bad %d, cannot mend!\n", res);
|
||||||
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
|
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
|
||||||
res = spiffs_page_delete(fs, cur_pix);
|
res = spiffs_page_delete(fs, cur_pix);
|
||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
|
44
cores/esp8266/spiffs/spiffs_config.h
Executable file → Normal file
44
cores/esp8266/spiffs/spiffs_config.h
Executable file → Normal file
@ -8,24 +8,11 @@
|
|||||||
#ifndef SPIFFS_CONFIG_H_
|
#ifndef SPIFFS_CONFIG_H_
|
||||||
#define SPIFFS_CONFIG_H_
|
#define SPIFFS_CONFIG_H_
|
||||||
|
|
||||||
// ----------- 8< ------------
|
|
||||||
// Following includes are for the linux test build of spiffs
|
|
||||||
// These may/should/must be removed/altered/replaced in your target
|
|
||||||
// #include "params_test.h"
|
|
||||||
//#include "c_stdio.h"
|
|
||||||
//#include "c_stdlib.h"
|
|
||||||
//#include "c_string.h"
|
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "c_types.h"
|
#include "c_types.h"
|
||||||
#include "stddef.h"
|
#include "stddef.h"
|
||||||
#include "osapi.h"
|
#include "osapi.h"
|
||||||
#include "ets_sys.h"
|
#include "ets_sys.h"
|
||||||
// ----------- >8 ------------
|
|
||||||
#define IRAM_ATTR __attribute__((section(".iram.text")))
|
|
||||||
#define STORE_TYPEDEF_ATTR __attribute__((aligned(4),packed))
|
|
||||||
#define STORE_ATTR __attribute__((aligned(4)))
|
|
||||||
|
|
||||||
#define SPIFFS_CHACHE 0
|
|
||||||
|
|
||||||
#define c_memcpy os_memcpy
|
#define c_memcpy os_memcpy
|
||||||
#define c_printf os_printf
|
#define c_printf os_printf
|
||||||
@ -56,24 +43,22 @@ typedef uint8_t u8_t;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// compile time switches
|
// compile time switches
|
||||||
#define debugf(fmt, ...) //os_printf(fmt"\r\n", ##__VA_ARGS__)
|
|
||||||
#define SYSTEM_ERROR(fmt, ...) //os_printf("ERROR: " fmt "\r\n", ##__VA_ARGS__)
|
|
||||||
|
|
||||||
// Set generic spiffs debug output call.
|
// Set generic spiffs debug output call.
|
||||||
#ifndef SPIFFS_DGB
|
#ifndef SPIFFS_DGB
|
||||||
#define SPIFFS_DBG(...) //os_printf(__VA_ARGS__)
|
#define SPIFFS_DBG(...) //c_printf(__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
// Set spiffs debug output call for garbage collecting.
|
// Set spiffs debug output call for garbage collecting.
|
||||||
#ifndef SPIFFS_GC_DGB
|
#ifndef SPIFFS_GC_DGB
|
||||||
#define SPIFFS_GC_DBG(...) //os_printf(__VA_ARGS__)
|
#define SPIFFS_GC_DBG(...) //c_printf(__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
// Set spiffs debug output call for caching.
|
// Set spiffs debug output call for caching.
|
||||||
#ifndef SPIFFS_CACHE_DGB
|
#ifndef SPIFFS_CACHE_DGB
|
||||||
#define SPIFFS_CACHE_DBG(...) //os_printf(__VA_ARGS__)
|
#define SPIFFS_CACHE_DBG(...) //c_printf(__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
// Set spiffs debug output call for system consistency checks.
|
// Set spiffs debug output call for system consistency checks.
|
||||||
#ifndef SPIFFS_CHECK_DGB
|
#ifndef SPIFFS_CHECK_DGB
|
||||||
#define SPIFFS_CHECK_DBG(...) //os_printf(__VA_ARGS__)
|
#define SPIFFS_CHECK_DBG(...) //c_printf(__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Enable/disable API functions to determine exact number of bytes
|
// Enable/disable API functions to determine exact number of bytes
|
||||||
@ -108,7 +93,7 @@ typedef uint8_t u8_t;
|
|||||||
|
|
||||||
// Define maximum number of gc runs to perform to reach desired free pages.
|
// Define maximum number of gc runs to perform to reach desired free pages.
|
||||||
#ifndef SPIFFS_GC_MAX_RUNS
|
#ifndef SPIFFS_GC_MAX_RUNS
|
||||||
#define SPIFFS_GC_MAX_RUNS 3
|
#define SPIFFS_GC_MAX_RUNS 5
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Enable/disable statistics on gc. Debug/test purpose only.
|
// Enable/disable statistics on gc. Debug/test purpose only.
|
||||||
@ -150,14 +135,22 @@ typedef uint8_t u8_t;
|
|||||||
#define SPIFFS_COPY_BUFFER_STACK (64)
|
#define SPIFFS_COPY_BUFFER_STACK (64)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Enable this to have an identifiable spiffs filesystem. This will look for
|
||||||
|
// a magic in all sectors to determine if this is a valid spiffs system or
|
||||||
|
// not on mount point. If not, SPIFFS_format must be called prior to mounting
|
||||||
|
// again.
|
||||||
|
#ifndef SPIFFS_USE_MAGIC
|
||||||
|
#define SPIFFS_USE_MAGIC (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level
|
// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level
|
||||||
// These should be defined on a multithreaded system
|
// These should be defined on a multithreaded system
|
||||||
|
|
||||||
// define this to entering a mutex if you're running on a multithreaded system
|
// define this to enter a mutex if you're running on a multithreaded system
|
||||||
#ifndef SPIFFS_LOCK
|
#ifndef SPIFFS_LOCK
|
||||||
#define SPIFFS_LOCK(fs)
|
#define SPIFFS_LOCK(fs)
|
||||||
#endif
|
#endif
|
||||||
// define this to exiting a mutex if you're running on a multithreaded system
|
// define this to exit a mutex if you're running on a multithreaded system
|
||||||
#ifndef SPIFFS_UNLOCK
|
#ifndef SPIFFS_UNLOCK
|
||||||
#define SPIFFS_UNLOCK(fs)
|
#define SPIFFS_UNLOCK(fs)
|
||||||
#endif
|
#endif
|
||||||
@ -190,7 +183,12 @@ typedef uint8_t u8_t;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set SPFIFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function
|
// Enable this if your target needs aligned data for index tables
|
||||||
|
#ifndef SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
|
||||||
|
#define SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set SPIFFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function
|
||||||
// in the api. This function will visualize all filesystem using given printf
|
// in the api. This function will visualize all filesystem using given printf
|
||||||
// function.
|
// function.
|
||||||
#ifndef SPIFFS_TEST_VISUALISATION
|
#ifndef SPIFFS_TEST_VISUALISATION
|
||||||
|
224
cores/esp8266/spiffs/spiffs_esp8266.c
Normal file
224
cores/esp8266/spiffs/spiffs_esp8266.c
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
#include "spiffs_esp8266.h"
|
||||||
|
#include "spi_flash.h"
|
||||||
|
#include "esp8266_peri.h"
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
FLASH ACCESS FUNCTIONS
|
||||||
|
*/
|
||||||
|
|
||||||
|
//lowest level sector erase method
|
||||||
|
bool flashmem_erase_sector( uint32_t sector_id ){
|
||||||
|
WDT_RESET();
|
||||||
|
noInterrupts();
|
||||||
|
bool erased = spi_flash_erase_sector( sector_id ) == SPI_FLASH_RESULT_OK;
|
||||||
|
interrupts();
|
||||||
|
return erased;
|
||||||
|
}
|
||||||
|
|
||||||
|
//lowest level data write method
|
||||||
|
uint32_t flashmem_write_internal( const void *from, uint32_t toaddr, uint32_t size ){
|
||||||
|
toaddr -= INTERNAL_FLASH_START_ADDRESS;
|
||||||
|
SpiFlashOpResult r;
|
||||||
|
const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1;
|
||||||
|
uint32_t *apbuf = NULL;
|
||||||
|
if(((uint32_t)from) & blkmask){
|
||||||
|
apbuf = (uint32_t *)os_malloc(size);
|
||||||
|
if(!apbuf)
|
||||||
|
return 0;
|
||||||
|
os_memcpy(apbuf, from, size);
|
||||||
|
}
|
||||||
|
WDT_RESET();
|
||||||
|
noInterrupts();
|
||||||
|
r = spi_flash_write(toaddr, apbuf?(uint32 *)apbuf:(uint32 *)from, size);
|
||||||
|
interrupts();
|
||||||
|
if(apbuf)
|
||||||
|
os_free(apbuf);
|
||||||
|
if(SPI_FLASH_RESULT_OK == r)
|
||||||
|
return size;
|
||||||
|
else{
|
||||||
|
SPIFFS_API_DBG_E( "ERROR in flash_write: r=%d at %08X\n", ( int )r, ( unsigned )toaddr+INTERNAL_FLASH_START_ADDRESS );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//lowest level data read method
|
||||||
|
uint32_t flashmem_read_internal( void *to, uint32_t fromaddr, uint32_t size ){
|
||||||
|
fromaddr -= INTERNAL_FLASH_START_ADDRESS;
|
||||||
|
SpiFlashOpResult r;
|
||||||
|
WDT_RESET();
|
||||||
|
noInterrupts();
|
||||||
|
r = spi_flash_read(fromaddr, (uint32 *)to, size);
|
||||||
|
interrupts();
|
||||||
|
if(SPI_FLASH_RESULT_OK == r)
|
||||||
|
return size;
|
||||||
|
else{
|
||||||
|
SPIFFS_API_DBG_E( "ERROR in flash_read: r=%d at %08X\n", ( int )r, ( unsigned )fromaddr+INTERNAL_FLASH_START_ADDRESS );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//mid level data write method
|
||||||
|
uint32_t flashmem_write( const void *from, uint32_t toaddr, uint32_t size ){
|
||||||
|
uint32_t temp, rest, ssize = size;
|
||||||
|
unsigned i;
|
||||||
|
char tmpdata[ INTERNAL_FLASH_WRITE_UNIT_SIZE ];
|
||||||
|
const uint8_t *pfrom = ( const uint8_t* )from;
|
||||||
|
const uint32_t blksize = INTERNAL_FLASH_WRITE_UNIT_SIZE;
|
||||||
|
const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1;
|
||||||
|
|
||||||
|
// Align the start
|
||||||
|
if(toaddr & blkmask){
|
||||||
|
rest = toaddr & blkmask;
|
||||||
|
temp = toaddr & ~blkmask; // this is the actual aligned address
|
||||||
|
// c_memcpy( tmpdata, ( const void* )temp, blksize );
|
||||||
|
flashmem_read_internal( tmpdata, temp, blksize );
|
||||||
|
for( i = rest; size && ( i < blksize ); i ++, size --, pfrom ++ )
|
||||||
|
tmpdata[ i ] = *pfrom;
|
||||||
|
flashmem_write_internal( tmpdata, temp, blksize );
|
||||||
|
if( size == 0 )
|
||||||
|
return ssize;
|
||||||
|
toaddr = temp + blksize;
|
||||||
|
}
|
||||||
|
// The start address is now a multiple of blksize
|
||||||
|
// Compute how many bytes we can write as multiples of blksize
|
||||||
|
rest = size & blkmask;
|
||||||
|
temp = size & ~blkmask;
|
||||||
|
// Program the blocks now
|
||||||
|
if(temp){
|
||||||
|
flashmem_write_internal( pfrom, toaddr, temp );
|
||||||
|
toaddr += temp;
|
||||||
|
pfrom += temp;
|
||||||
|
}
|
||||||
|
// And the final part of a block if needed
|
||||||
|
if(rest){
|
||||||
|
// c_memcpy( tmpdata, ( const void* )toaddr, blksize );
|
||||||
|
flashmem_read_internal( tmpdata, toaddr, blksize );
|
||||||
|
for( i = 0; size && ( i < rest ); i ++, size --, pfrom ++ )
|
||||||
|
tmpdata[ i ] = *pfrom;
|
||||||
|
flashmem_write_internal( tmpdata, toaddr, blksize );
|
||||||
|
}
|
||||||
|
return ssize;
|
||||||
|
}
|
||||||
|
|
||||||
|
//mid level data write method
|
||||||
|
uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size ){
|
||||||
|
uint32_t temp, rest, ssize = size;
|
||||||
|
unsigned i;
|
||||||
|
char tmpdata[ INTERNAL_FLASH_READ_UNIT_SIZE ];
|
||||||
|
uint8_t *pto = ( uint8_t* )to;
|
||||||
|
const uint32_t blksize = INTERNAL_FLASH_READ_UNIT_SIZE;
|
||||||
|
const uint32_t blkmask = INTERNAL_FLASH_READ_UNIT_SIZE - 1;
|
||||||
|
|
||||||
|
// Align the start
|
||||||
|
if(fromaddr & blkmask){
|
||||||
|
rest = fromaddr & blkmask;
|
||||||
|
temp = fromaddr & ~blkmask; // this is the actual aligned address
|
||||||
|
flashmem_read_internal( tmpdata, temp, blksize );
|
||||||
|
for( i = rest; size && ( i < blksize ); i ++, size --, pto ++ )
|
||||||
|
*pto = tmpdata[ i ];
|
||||||
|
|
||||||
|
if( size == 0 )
|
||||||
|
return ssize;
|
||||||
|
fromaddr = temp + blksize;
|
||||||
|
}
|
||||||
|
// The start address is now a multiple of blksize
|
||||||
|
// Compute how many bytes we can read as multiples of blksize
|
||||||
|
rest = size & blkmask;
|
||||||
|
temp = size & ~blkmask;
|
||||||
|
// Program the blocks now
|
||||||
|
if(temp){
|
||||||
|
flashmem_read_internal( pto, fromaddr, temp );
|
||||||
|
fromaddr += temp;
|
||||||
|
pto += temp;
|
||||||
|
}
|
||||||
|
// And the final part of a block if needed
|
||||||
|
if(rest){
|
||||||
|
flashmem_read_internal( tmpdata, fromaddr, blksize );
|
||||||
|
for( i = 0; size && ( i < rest ); i ++, size --, pto ++ )
|
||||||
|
*pto = tmpdata[ i ];
|
||||||
|
}
|
||||||
|
return ssize;
|
||||||
|
}
|
||||||
|
|
||||||
|
//shorthand when start and end addresses of the sector are not needed
|
||||||
|
uint32_t flashmem_get_sector_of_address( uint32_t addr ){
|
||||||
|
return (addr - INTERNAL_FLASH_START_ADDRESS) / INTERNAL_FLASH_SECTOR_SIZE;;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
SPIFFS BOOTSTRAP
|
||||||
|
*/
|
||||||
|
|
||||||
|
//SPIFFS Address Range (defined in eagle ld)
|
||||||
|
extern uint32_t _SPIFFS_start;
|
||||||
|
extern uint32_t _SPIFFS_end;
|
||||||
|
|
||||||
|
//SPIFFS Storage Handle
|
||||||
|
spiffs _filesystemStorageHandle;
|
||||||
|
|
||||||
|
//SPIFFS Buffers (INTERNAL_FLASH_PAGE_SIZE = 256) Total 1792 bytes
|
||||||
|
static u8_t spiffs_work_buf[INTERNAL_FLASH_PAGE_SIZE*2]; //512 bytes
|
||||||
|
static u8_t spiffs_fds[32*4]; //128 bytes
|
||||||
|
static u8_t spiffs_cache[(INTERNAL_FLASH_PAGE_SIZE+32)*4]; //1152 bytes
|
||||||
|
|
||||||
|
//SPIFFS API Read CallBack
|
||||||
|
static s32_t api_spiffs_read(u32_t addr, u32_t size, u8_t *dst){
|
||||||
|
SPIFFS_API_DBG_V("api_spiffs_read: 0x%08x len: %u\n", addr, size);
|
||||||
|
flashmem_read(dst, addr, size);
|
||||||
|
return SPIFFS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//SPIFFS API Write CallBack
|
||||||
|
static s32_t api_spiffs_write(u32_t addr, u32_t size, u8_t *src){
|
||||||
|
SPIFFS_API_DBG_V("api_spiffs_write: 0x%08x len: %u\n", addr, size);
|
||||||
|
flashmem_write(src, addr, size);
|
||||||
|
return SPIFFS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//SPIFFS API Erase CallBack
|
||||||
|
static s32_t api_spiffs_erase(u32_t addr, u32_t size){
|
||||||
|
SPIFFS_API_DBG_V("api_spiffs_erase: 0x%08x len: %u\n", addr, size);
|
||||||
|
u32_t sect_first = flashmem_get_sector_of_address(addr);
|
||||||
|
u32_t sect_last = flashmem_get_sector_of_address(addr+size);
|
||||||
|
while( sect_first <= sect_last )
|
||||||
|
if( !flashmem_erase_sector( sect_first ++ ) )
|
||||||
|
return SPIFFS_ERR_INTERNAL;
|
||||||
|
return SPIFFS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Our own SPIFFS Setup Method
|
||||||
|
// All of the above gets put in the configuration
|
||||||
|
// and a mount attempt is made, initializing the storage handle
|
||||||
|
// that is used in all further api calls
|
||||||
|
s32_t spiffs_mount(){
|
||||||
|
u32_t start_address = (u32_t)&_SPIFFS_start;
|
||||||
|
u32_t end_address = (u32_t)&_SPIFFS_end;
|
||||||
|
if (start_address == 0 || start_address >= end_address){
|
||||||
|
SPIFFS_API_DBG_E("Can't start file system, wrong address");
|
||||||
|
return SPIFFS_ERR_NOT_CONFIGURED;
|
||||||
|
}
|
||||||
|
|
||||||
|
spiffs_config cfg = {0};
|
||||||
|
cfg.phys_addr = start_address;
|
||||||
|
cfg.phys_size = end_address - start_address;
|
||||||
|
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 = INTERNAL_FLASH_PAGE_SIZE; // according to datasheet
|
||||||
|
cfg.hal_read_f = api_spiffs_read;
|
||||||
|
cfg.hal_write_f = api_spiffs_write;
|
||||||
|
cfg.hal_erase_f = api_spiffs_erase;
|
||||||
|
|
||||||
|
SPIFFS_API_DBG_V("spiffs_mount: start:%x, size:%d Kb\n", cfg.phys_addr, cfg.phys_size / 1024);
|
||||||
|
|
||||||
|
s32_t res = SPIFFS_mount(&_filesystemStorageHandle,
|
||||||
|
&cfg,
|
||||||
|
spiffs_work_buf,
|
||||||
|
spiffs_fds,
|
||||||
|
sizeof(spiffs_fds),
|
||||||
|
spiffs_cache,
|
||||||
|
sizeof(spiffs_cache),
|
||||||
|
NULL);
|
||||||
|
SPIFFS_API_DBG_V("spiffs_mount: %d\n", res);
|
||||||
|
return res;
|
||||||
|
}
|
40
cores/esp8266/spiffs/spiffs_esp8266.h
Normal file
40
cores/esp8266/spiffs/spiffs_esp8266.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef SYSTEM_FLASHMEM_H_
|
||||||
|
#define SYSTEM_FLASHMEM_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "spiffs.h"
|
||||||
|
|
||||||
|
/*******************
|
||||||
|
The W25Q32BV array is organized into 16,384 programmable pages of 256-bytes each. Up to 256 bytes can be programmed at a time.
|
||||||
|
Pages can be erased in groups of 16 (4KB sector erase), groups of 128 (32KB block erase), groups of 256 (64KB block erase) or
|
||||||
|
the entire chip (chip erase). The W25Q32BV has 1,024 erasable sectors and 64 erasable blocks respectively.
|
||||||
|
The small 4KB sectors allow for greater flexibility in applications that require data and parameter storage.
|
||||||
|
********************/
|
||||||
|
|
||||||
|
#define SPIFFS_API_DBG_V(fmt, ...) //os_printf(fmt, ##__VA_ARGS__)
|
||||||
|
#define SPIFFS_API_DBG_E(fmt, ...) //os_printf("ERROR: " fmt , ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define INTERNAL_FLASH_PAGE_SIZE 256
|
||||||
|
#define INTERNAL_FLASH_SECTOR_SIZE 4096
|
||||||
|
#define INTERNAL_FLASH_START_ADDRESS 0x40200000
|
||||||
|
|
||||||
|
#define INTERNAL_FLASH_WRITE_UNIT_SIZE 4
|
||||||
|
#define INTERNAL_FLASH_READ_UNIT_SIZE 4
|
||||||
|
|
||||||
|
extern spiffs _filesystemStorageHandle;
|
||||||
|
|
||||||
|
extern uint32_t flashmem_write( const void *from, uint32_t toaddr, uint32_t size );
|
||||||
|
extern uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size );
|
||||||
|
extern bool flashmem_erase_sector( uint32_t sector_id );
|
||||||
|
uint32_t flashmem_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend );
|
||||||
|
uint32_t flashmem_get_sector_of_address( uint32_t addr );
|
||||||
|
s32_t spiffs_mount();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SYSTEM_FLASHMEM_H_ */
|
@ -1,224 +0,0 @@
|
|||||||
#include "flashmem.h"
|
|
||||||
#include "esp8266_peri.h"
|
|
||||||
|
|
||||||
// Based on NodeMCU platform_flash
|
|
||||||
// https://github.com/nodemcu/nodemcu-firmware
|
|
||||||
|
|
||||||
extern uint32_t _SPIFFS_start;
|
|
||||||
|
|
||||||
uint32_t flashmem_write( const void *from, uint32_t toaddr, uint32_t size )
|
|
||||||
{
|
|
||||||
uint32_t temp, rest, ssize = size;
|
|
||||||
unsigned i;
|
|
||||||
char tmpdata[ INTERNAL_FLASH_WRITE_UNIT_SIZE ];
|
|
||||||
const uint8_t *pfrom = ( const uint8_t* )from;
|
|
||||||
const uint32_t blksize = INTERNAL_FLASH_WRITE_UNIT_SIZE;
|
|
||||||
const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1;
|
|
||||||
|
|
||||||
// Align the start
|
|
||||||
if( toaddr & blkmask )
|
|
||||||
{
|
|
||||||
rest = toaddr & blkmask;
|
|
||||||
temp = toaddr & ~blkmask; // this is the actual aligned address
|
|
||||||
// c_memcpy( tmpdata, ( const void* )temp, blksize );
|
|
||||||
flashmem_read_internal( tmpdata, temp, blksize );
|
|
||||||
for( i = rest; size && ( i < blksize ); i ++, size --, pfrom ++ )
|
|
||||||
tmpdata[ i ] = *pfrom;
|
|
||||||
flashmem_write_internal( tmpdata, temp, blksize );
|
|
||||||
if( size == 0 )
|
|
||||||
return ssize;
|
|
||||||
toaddr = temp + blksize;
|
|
||||||
}
|
|
||||||
// The start address is now a multiple of blksize
|
|
||||||
// Compute how many bytes we can write as multiples of blksize
|
|
||||||
rest = size & blkmask;
|
|
||||||
temp = size & ~blkmask;
|
|
||||||
// Program the blocks now
|
|
||||||
if( temp )
|
|
||||||
{
|
|
||||||
flashmem_write_internal( pfrom, toaddr, temp );
|
|
||||||
toaddr += temp;
|
|
||||||
pfrom += temp;
|
|
||||||
}
|
|
||||||
// And the final part of a block if needed
|
|
||||||
if( rest )
|
|
||||||
{
|
|
||||||
// c_memcpy( tmpdata, ( const void* )toaddr, blksize );
|
|
||||||
flashmem_read_internal( tmpdata, toaddr, blksize );
|
|
||||||
for( i = 0; size && ( i < rest ); i ++, size --, pfrom ++ )
|
|
||||||
tmpdata[ i ] = *pfrom;
|
|
||||||
flashmem_write_internal( tmpdata, toaddr, blksize );
|
|
||||||
}
|
|
||||||
return ssize;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size )
|
|
||||||
{
|
|
||||||
uint32_t temp, rest, ssize = size;
|
|
||||||
unsigned i;
|
|
||||||
char tmpdata[ INTERNAL_FLASH_READ_UNIT_SIZE ];
|
|
||||||
uint8_t *pto = ( uint8_t* )to;
|
|
||||||
const uint32_t blksize = INTERNAL_FLASH_READ_UNIT_SIZE;
|
|
||||||
const uint32_t blkmask = INTERNAL_FLASH_READ_UNIT_SIZE - 1;
|
|
||||||
|
|
||||||
// Align the start
|
|
||||||
if( fromaddr & blkmask )
|
|
||||||
{
|
|
||||||
rest = fromaddr & blkmask;
|
|
||||||
temp = fromaddr & ~blkmask; // this is the actual aligned address
|
|
||||||
flashmem_read_internal( tmpdata, temp, blksize );
|
|
||||||
for( i = rest; size && ( i < blksize ); i ++, size --, pto ++ )
|
|
||||||
*pto = tmpdata[ i ];
|
|
||||||
|
|
||||||
if( size == 0 )
|
|
||||||
return ssize;
|
|
||||||
fromaddr = temp + blksize;
|
|
||||||
}
|
|
||||||
// The start address is now a multiple of blksize
|
|
||||||
// Compute how many bytes we can read as multiples of blksize
|
|
||||||
rest = size & blkmask;
|
|
||||||
temp = size & ~blkmask;
|
|
||||||
// Program the blocks now
|
|
||||||
if( temp )
|
|
||||||
{
|
|
||||||
flashmem_read_internal( pto, fromaddr, temp );
|
|
||||||
fromaddr += temp;
|
|
||||||
pto += temp;
|
|
||||||
}
|
|
||||||
// And the final part of a block if needed
|
|
||||||
if( rest )
|
|
||||||
{
|
|
||||||
flashmem_read_internal( tmpdata, fromaddr, blksize );
|
|
||||||
for( i = 0; size && ( i < rest ); i ++, size --, pto ++ )
|
|
||||||
*pto = tmpdata[ i ];
|
|
||||||
}
|
|
||||||
return ssize;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool flashmem_erase_sector( uint32_t sector_id )
|
|
||||||
{
|
|
||||||
WRITE_PERI_REG(0x60000914, 0x73);
|
|
||||||
return spi_flash_erase_sector( sector_id ) == SPI_FLASH_RESULT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
SPIFlashInfo flashmem_get_info()
|
|
||||||
{
|
|
||||||
volatile SPIFlashInfo spi_flash_info STORE_ATTR;
|
|
||||||
spi_flash_info = *((SPIFlashInfo *)(INTERNAL_FLASH_START_ADDRESS));
|
|
||||||
return spi_flash_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t flashmem_get_size_type()
|
|
||||||
{
|
|
||||||
return flashmem_get_info().size;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t flashmem_get_size_bytes()
|
|
||||||
{
|
|
||||||
uint32_t flash_size = 0;
|
|
||||||
switch (flashmem_get_info().size)
|
|
||||||
{
|
|
||||||
case SIZE_2MBIT:
|
|
||||||
// 2Mbit, 256kByte
|
|
||||||
flash_size = 256 * 1024;
|
|
||||||
break;
|
|
||||||
case SIZE_4MBIT:
|
|
||||||
// 4Mbit, 512kByte
|
|
||||||
flash_size = 512 * 1024;
|
|
||||||
break;
|
|
||||||
case SIZE_8MBIT:
|
|
||||||
// 8Mbit, 1MByte
|
|
||||||
flash_size = 1 * 1024 * 1024;
|
|
||||||
break;
|
|
||||||
case SIZE_16MBIT:
|
|
||||||
// 16Mbit, 2MByte
|
|
||||||
flash_size = 2 * 1024 * 1024;
|
|
||||||
break;
|
|
||||||
case SIZE_32MBIT:
|
|
||||||
// 32Mbit, 4MByte
|
|
||||||
flash_size = 4 * 1024 * 1024;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Unknown flash size, fall back mode.
|
|
||||||
flash_size = 512 * 1024;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return flash_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t flashmem_get_size_sectors()
|
|
||||||
{
|
|
||||||
return flashmem_get_size_bytes() / SPI_FLASH_SEC_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function: find the flash sector in which an address resides
|
|
||||||
// Return the sector number, as well as the start and end address of the sector
|
|
||||||
uint32_t flashmem_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend )
|
|
||||||
{
|
|
||||||
address -= INTERNAL_FLASH_START_ADDRESS;
|
|
||||||
// All the sectors in the flash have the same size, so just align the address
|
|
||||||
uint32_t sect_id = address / INTERNAL_FLASH_SECTOR_SIZE;
|
|
||||||
|
|
||||||
if( pstart )
|
|
||||||
*pstart = sect_id * INTERNAL_FLASH_SECTOR_SIZE + INTERNAL_FLASH_START_ADDRESS;
|
|
||||||
if( pend )
|
|
||||||
*pend = ( sect_id + 1 ) * INTERNAL_FLASH_SECTOR_SIZE + INTERNAL_FLASH_START_ADDRESS - 1;
|
|
||||||
return sect_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t flashmem_get_sector_of_address( uint32_t addr )
|
|
||||||
{
|
|
||||||
return flashmem_find_sector( addr, NULL, NULL );
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
uint32_t flashmem_write_internal( const void *from, uint32_t toaddr, uint32_t size )
|
|
||||||
{
|
|
||||||
toaddr -= INTERNAL_FLASH_START_ADDRESS;
|
|
||||||
SpiFlashOpResult r;
|
|
||||||
const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1;
|
|
||||||
uint32_t *apbuf = NULL;
|
|
||||||
if( ((uint32_t)from) & blkmask ){
|
|
||||||
apbuf = (uint32_t *)os_malloc(size);
|
|
||||||
if(!apbuf)
|
|
||||||
return 0;
|
|
||||||
os_memcpy(apbuf, from, size);
|
|
||||||
}
|
|
||||||
WDT_RESET();
|
|
||||||
r = spi_flash_write(toaddr, apbuf?(uint32 *)apbuf:(uint32 *)from, size);
|
|
||||||
if(apbuf)
|
|
||||||
os_free(apbuf);
|
|
||||||
if(SPI_FLASH_RESULT_OK == r)
|
|
||||||
return size;
|
|
||||||
else{
|
|
||||||
SYSTEM_ERROR( "ERROR in flash_write: r=%d at %08X\n", ( int )r, ( unsigned )toaddr+INTERNAL_FLASH_START_ADDRESS );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t flashmem_read_internal( void *to, uint32_t fromaddr, uint32_t size )
|
|
||||||
{
|
|
||||||
fromaddr -= INTERNAL_FLASH_START_ADDRESS;
|
|
||||||
SpiFlashOpResult r;
|
|
||||||
WDT_RESET();
|
|
||||||
r = spi_flash_read(fromaddr, (uint32 *)to, size);
|
|
||||||
if(SPI_FLASH_RESULT_OK == r)
|
|
||||||
return size;
|
|
||||||
else{
|
|
||||||
SYSTEM_ERROR( "ERROR in flash_read: r=%d at %08X\n", ( int )r, ( unsigned )fromaddr+INTERNAL_FLASH_START_ADDRESS );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t flashmem_get_first_free_block_address(){
|
|
||||||
if ((uint32_t)&_SPIFFS_start == 0){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
debugf("_SPIFFS_start:%08x\n", (uint32_t)&_SPIFFS_start);
|
|
||||||
|
|
||||||
// Round the total used flash size to the closest flash block address
|
|
||||||
uint32_t end;
|
|
||||||
flashmem_find_sector( (uint32_t)&_SPIFFS_start - 1, NULL, &end);
|
|
||||||
return end + 1;
|
|
||||||
}
|
|
80
cores/esp8266/spiffs/spiffs_gc.c
Executable file → Normal file
80
cores/esp8266/spiffs/spiffs_gc.c
Executable file → Normal file
@ -8,31 +8,11 @@ static s32_t spiffs_gc_erase_block(
|
|||||||
spiffs *fs,
|
spiffs *fs,
|
||||||
spiffs_block_ix bix) {
|
spiffs_block_ix bix) {
|
||||||
s32_t res;
|
s32_t res;
|
||||||
u32_t addr = SPIFFS_BLOCK_TO_PADDR(fs, bix);
|
|
||||||
s32_t size = SPIFFS_CFG_LOG_BLOCK_SZ(fs);
|
|
||||||
|
|
||||||
SPIFFS_GC_DBG("gc: erase block %d\n", bix);
|
SPIFFS_GC_DBG("gc: erase block %d\n", bix);
|
||||||
|
res = spiffs_erase_block(fs, bix);
|
||||||
// here we ignore res, just try erasing the block
|
|
||||||
while (size > 0) {
|
|
||||||
SPIFFS_GC_DBG("gc: erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
|
||||||
(void)fs->cfg.hal_erase_f(addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
|
||||||
addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs);
|
|
||||||
size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs);
|
|
||||||
}
|
|
||||||
fs->free_blocks++;
|
|
||||||
|
|
||||||
// register erase count for this block
|
|
||||||
res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
|
|
||||||
SPIFFS_ERASE_COUNT_PADDR(fs, bix),
|
|
||||||
sizeof(spiffs_obj_id), (u8_t *)&fs->max_erase_count);
|
|
||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
|
|
||||||
fs->max_erase_count++;
|
|
||||||
if (fs->max_erase_count == SPIFFS_OBJ_ID_IX_FLAG) {
|
|
||||||
fs->max_erase_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if SPIFFS_CACHE
|
#if SPIFFS_CACHE
|
||||||
{
|
{
|
||||||
u32_t i;
|
u32_t i;
|
||||||
@ -119,17 +99,25 @@ s32_t spiffs_gc_check(
|
|||||||
spiffs *fs,
|
spiffs *fs,
|
||||||
u32_t len) {
|
u32_t len) {
|
||||||
s32_t res;
|
s32_t res;
|
||||||
u32_t free_pages =
|
s32_t free_pages =
|
||||||
(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * fs->block_count
|
(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count-2)
|
||||||
- fs->stats_p_allocated - fs->stats_p_deleted;
|
- fs->stats_p_allocated - fs->stats_p_deleted;
|
||||||
int tries = 0;
|
int tries = 0;
|
||||||
|
|
||||||
if (fs->free_blocks > 3 &&
|
if (fs->free_blocks > 3 &&
|
||||||
len < free_pages * SPIFFS_DATA_PAGE_SIZE(fs)) {
|
(s32_t)len < free_pages * (s32_t)SPIFFS_DATA_PAGE_SIZE(fs)) {
|
||||||
return SPIFFS_OK;
|
return SPIFFS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("gcing started %d dirty, blocks %d free, want %d bytes\n", fs->stats_p_allocated + fs->stats_p_deleted, fs->free_blocks, len);
|
u32_t needed_pages = (len + SPIFFS_DATA_PAGE_SIZE(fs) - 1) / SPIFFS_DATA_PAGE_SIZE(fs);
|
||||||
|
// if (fs->free_blocks <= 2 && (s32_t)needed_pages > free_pages) {
|
||||||
|
// SPIFFS_GC_DBG("gc: full freeblk:%d needed:%d free:%d dele:%d\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted);
|
||||||
|
// return SPIFFS_ERR_FULL;
|
||||||
|
// }
|
||||||
|
if ((s32_t)needed_pages > (s32_t)(free_pages + fs->stats_p_deleted)) {
|
||||||
|
SPIFFS_GC_DBG("gc_check: full freeblk:%d needed:%d free:%d dele:%d\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted);
|
||||||
|
return SPIFFS_ERR_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
SPIFFS_GC_DBG("\ngc_check #%d: run gc free_blocks:%d pfree:%d pallo:%d pdele:%d [%d] len:%d of %d\n",
|
SPIFFS_GC_DBG("\ngc_check #%d: run gc free_blocks:%d pfree:%d pallo:%d pdele:%d [%d] len:%d of %d\n",
|
||||||
@ -140,18 +128,20 @@ s32_t spiffs_gc_check(
|
|||||||
spiffs_block_ix *cands;
|
spiffs_block_ix *cands;
|
||||||
int count;
|
int count;
|
||||||
spiffs_block_ix cand;
|
spiffs_block_ix cand;
|
||||||
res = spiffs_gc_find_candidate(fs, &cands, &count);
|
s32_t prev_free_pages = free_pages;
|
||||||
|
// if the fs is crammed, ignore block age when selecting candidate - kind of a bad state
|
||||||
|
res = spiffs_gc_find_candidate(fs, &cands, &count, free_pages <= 0);
|
||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
SPIFFS_GC_DBG("gc_check: no candidates, return\n");
|
SPIFFS_GC_DBG("gc_check: no candidates, return\n");
|
||||||
return res;
|
return (s32_t)needed_pages < free_pages ? SPIFFS_OK : SPIFFS_ERR_FULL;
|
||||||
}
|
}
|
||||||
#if SPIFFS_GC_STATS
|
#if SPIFFS_GC_STATS
|
||||||
fs->stats_gc_runs++;
|
fs->stats_gc_runs++;
|
||||||
#endif
|
#endif
|
||||||
cand = cands[0];
|
cand = cands[0];
|
||||||
fs->cleaning = 1;
|
fs->cleaning = 1;
|
||||||
//printf("gcing: cleaning block %d\n", cand);
|
//c_printf("gcing: cleaning block %d\n", cand);
|
||||||
res = spiffs_gc_clean(fs, cand);
|
res = spiffs_gc_clean(fs, cand);
|
||||||
fs->cleaning = 0;
|
fs->cleaning = 0;
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
@ -168,16 +158,28 @@ s32_t spiffs_gc_check(
|
|||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
|
|
||||||
free_pages =
|
free_pages =
|
||||||
(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * fs->block_count
|
(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count - 2)
|
||||||
- fs->stats_p_allocated - fs->stats_p_deleted;
|
- fs->stats_p_allocated - fs->stats_p_deleted;
|
||||||
|
|
||||||
} while (++tries < SPIFFS_GC_MAX_RUNS && (fs->free_blocks <= 2 ||
|
if (prev_free_pages <= 0 && prev_free_pages == free_pages) {
|
||||||
len > free_pages*SPIFFS_DATA_PAGE_SIZE(fs)));
|
// abort early to reduce wear, at least tried once
|
||||||
SPIFFS_GC_DBG("gc_check: finished\n");
|
SPIFFS_GC_DBG("gc_check: early abort, no result on gc when fs crammed\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
//printf("gcing finished %d dirty, blocks %d free, %d pages free, %d tries, res %d\n",
|
} while (++tries < SPIFFS_GC_MAX_RUNS && (fs->free_blocks <= 2 ||
|
||||||
// fs->stats_p_allocated + fs->stats_p_deleted,
|
(s32_t)len > free_pages*(s32_t)SPIFFS_DATA_PAGE_SIZE(fs)));
|
||||||
// fs->free_blocks, free_pages, tries, res);
|
|
||||||
|
free_pages =
|
||||||
|
(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count - 2)
|
||||||
|
- fs->stats_p_allocated - fs->stats_p_deleted;
|
||||||
|
if ((s32_t)len > free_pages*(s32_t)SPIFFS_DATA_PAGE_SIZE(fs)) {
|
||||||
|
res = SPIFFS_ERR_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIFFS_GC_DBG("gc_check: finished, %d dirty, blocks %d free, %d pages free, %d tries, res %d\n",
|
||||||
|
fs->stats_p_allocated + fs->stats_p_deleted,
|
||||||
|
fs->free_blocks, free_pages, tries, res);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -223,7 +225,8 @@ s32_t spiffs_gc_erase_page_stats(
|
|||||||
s32_t spiffs_gc_find_candidate(
|
s32_t spiffs_gc_find_candidate(
|
||||||
spiffs *fs,
|
spiffs *fs,
|
||||||
spiffs_block_ix **block_candidates,
|
spiffs_block_ix **block_candidates,
|
||||||
int *candidate_count) {
|
int *candidate_count,
|
||||||
|
char fs_crammed) {
|
||||||
s32_t res = SPIFFS_OK;
|
s32_t res = SPIFFS_OK;
|
||||||
u32_t blocks = fs->block_count;
|
u32_t blocks = fs->block_count;
|
||||||
spiffs_block_ix cur_block = 0;
|
spiffs_block_ix cur_block = 0;
|
||||||
@ -249,6 +252,7 @@ s32_t spiffs_gc_find_candidate(
|
|||||||
while (res == SPIFFS_OK && blocks--) {
|
while (res == SPIFFS_OK && blocks--) {
|
||||||
u16_t deleted_pages_in_block = 0;
|
u16_t deleted_pages_in_block = 0;
|
||||||
u16_t used_pages_in_block = 0;
|
u16_t used_pages_in_block = 0;
|
||||||
|
|
||||||
int obj_lookup_page = 0;
|
int obj_lookup_page = 0;
|
||||||
// check each object lookup page
|
// check each object lookup page
|
||||||
while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
|
while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
|
||||||
@ -295,9 +299,9 @@ s32_t spiffs_gc_find_candidate(
|
|||||||
s32_t score =
|
s32_t score =
|
||||||
deleted_pages_in_block * SPIFFS_GC_HEUR_W_DELET +
|
deleted_pages_in_block * SPIFFS_GC_HEUR_W_DELET +
|
||||||
used_pages_in_block * SPIFFS_GC_HEUR_W_USED +
|
used_pages_in_block * SPIFFS_GC_HEUR_W_USED +
|
||||||
erase_age * SPIFFS_GC_HEUR_W_ERASE_AGE;
|
erase_age * (fs_crammed ? 0 : SPIFFS_GC_HEUR_W_ERASE_AGE);
|
||||||
int cand_ix = 0;
|
int cand_ix = 0;
|
||||||
SPIFFS_GC_DBG("\ngc_check: bix:%d del:%d use:%d score:%d\n", cur_block, deleted_pages_in_block, used_pages_in_block, score);
|
SPIFFS_GC_DBG("gc_check: bix:%d del:%d use:%d score:%d\n", cur_block, deleted_pages_in_block, used_pages_in_block, score);
|
||||||
while (cand_ix < max_candidates) {
|
while (cand_ix < max_candidates) {
|
||||||
if (cand_blocks[cand_ix] == (spiffs_block_ix)-1) {
|
if (cand_blocks[cand_ix] == (spiffs_block_ix)-1) {
|
||||||
cand_blocks[cand_ix] = cur_block;
|
cand_blocks[cand_ix] = cur_block;
|
||||||
|
166
cores/esp8266/spiffs/spiffs_hydrogen.c
Executable file → Normal file
166
cores/esp8266/spiffs/spiffs_hydrogen.c
Executable file → Normal file
@ -21,6 +21,36 @@ u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages) {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
u8_t SPIFFS_mounted(spiffs *fs) {
|
||||||
|
return SPIFFS_CHECK_MOUNT(fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32_t SPIFFS_format(spiffs *fs) {
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
|
if (SPIFFS_CHECK_MOUNT(fs)) {
|
||||||
|
fs->err_code = SPIFFS_ERR_MOUNTED;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32_t res;
|
||||||
|
SPIFFS_LOCK(fs);
|
||||||
|
|
||||||
|
spiffs_block_ix bix = 0;
|
||||||
|
while (bix < fs->block_count) {
|
||||||
|
fs->max_erase_count = 0;
|
||||||
|
res = spiffs_erase_block(fs, bix);
|
||||||
|
if (res != SPIFFS_OK) {
|
||||||
|
res = SPIFFS_ERR_ERASE_FAIL;
|
||||||
|
}
|
||||||
|
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||||
|
bix++;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIFFS_UNLOCK(fs);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
||||||
u8_t *fd_space, u32_t fd_space_size,
|
u8_t *fd_space, u32_t fd_space_size,
|
||||||
void *cache, u32_t cache_size,
|
void *cache, u32_t cache_size,
|
||||||
@ -34,10 +64,10 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
|||||||
c_memset(fd_space, 0, fd_space_size);
|
c_memset(fd_space, 0, fd_space_size);
|
||||||
// align fd_space pointer to pointer size byte boundary, below is safe
|
// align fd_space pointer to pointer size byte boundary, below is safe
|
||||||
u8_t ptr_size = sizeof(void*);
|
u8_t ptr_size = sizeof(void*);
|
||||||
// #pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
// #pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
|
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
|
||||||
u8_t addr_lsb = (u8_t)(((u32_t)fd_space) & (ptr_size-1));
|
u8_t addr_lsb = ((u8_t)fd_space) & (ptr_size-1);
|
||||||
// #pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
if (addr_lsb) {
|
if (addr_lsb) {
|
||||||
fd_space += (ptr_size-addr_lsb);
|
fd_space += (ptr_size-addr_lsb);
|
||||||
fd_space_size -= (ptr_size-addr_lsb);
|
fd_space_size -= (ptr_size-addr_lsb);
|
||||||
@ -46,10 +76,10 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
|||||||
fs->fd_count = (fd_space_size/sizeof(spiffs_fd));
|
fs->fd_count = (fd_space_size/sizeof(spiffs_fd));
|
||||||
|
|
||||||
// align cache pointer to 4 byte boundary, below is safe
|
// align cache pointer to 4 byte boundary, below is safe
|
||||||
// #pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
// #pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
|
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
|
||||||
addr_lsb = (u8_t)(((u32_t)cache) & (ptr_size-1));
|
addr_lsb = ((u8_t)cache) & (ptr_size-1);
|
||||||
// #pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
if (addr_lsb) {
|
if (addr_lsb) {
|
||||||
u8_t *cache_8 = (u8_t *)cache;
|
u8_t *cache_8 = (u8_t *)cache;
|
||||||
cache_8 += (ptr_size-addr_lsb);
|
cache_8 += (ptr_size-addr_lsb);
|
||||||
@ -65,7 +95,16 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
|||||||
spiffs_cache_init(fs);
|
spiffs_cache_init(fs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s32_t res = spiffs_obj_lu_scan(fs);
|
s32_t res;
|
||||||
|
|
||||||
|
#if SPIFFS_USE_MAGIC
|
||||||
|
res = SPIFFS_CHECK_MAGIC_POSSIBLE(fs) ? SPIFFS_OK : SPIFFS_ERR_MAGIC_NOT_POSSIBLE;
|
||||||
|
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fs->config_magic = SPIFFS_CONFIG_MAGIC;
|
||||||
|
|
||||||
|
res = spiffs_obj_lu_scan(fs);
|
||||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||||
|
|
||||||
SPIFFS_DBG("page index byte len: %d\n", SPIFFS_CFG_LOG_PAGE_SZ(fs));
|
SPIFFS_DBG("page index byte len: %d\n", SPIFFS_CFG_LOG_PAGE_SZ(fs));
|
||||||
@ -79,13 +118,15 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
|||||||
|
|
||||||
fs->check_cb_f = check_cb_f;
|
fs->check_cb_f = check_cb_f;
|
||||||
|
|
||||||
|
fs->mounted = 1;
|
||||||
|
|
||||||
SPIFFS_UNLOCK(fs);
|
SPIFFS_UNLOCK(fs);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPIFFS_unmount(spiffs *fs) {
|
void SPIFFS_unmount(spiffs *fs) {
|
||||||
if (!SPIFFS_CHECK_MOUNT(fs)) return;
|
if (!SPIFFS_CHECK_CFG(fs) || !SPIFFS_CHECK_MOUNT(fs)) return;
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
u32_t i;
|
u32_t i;
|
||||||
spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
|
spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
|
||||||
@ -98,16 +139,22 @@ void SPIFFS_unmount(spiffs *fs) {
|
|||||||
spiffs_fd_return(fs, cur_fd->file_nbr);
|
spiffs_fd_return(fs, cur_fd->file_nbr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fs->block_count = 0;
|
fs->mounted = 0;
|
||||||
|
|
||||||
SPIFFS_UNLOCK(fs);
|
SPIFFS_UNLOCK(fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
s32_t SPIFFS_errno(spiffs *fs) {
|
s32_t SPIFFS_errno(spiffs *fs) {
|
||||||
return fs->errno;
|
return fs->err_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode) {
|
void SPIFFS_clearerr(spiffs *fs) {
|
||||||
|
fs->err_code = SPIFFS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32_t SPIFFS_creat(spiffs *fs, char *path, spiffs_mode mode) {
|
||||||
(void)mode;
|
(void)mode;
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(fs);
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
spiffs_obj_id obj_id;
|
spiffs_obj_id obj_id;
|
||||||
@ -121,8 +168,9 @@ s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode mode) {
|
spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode mode) {
|
||||||
(void)mode;
|
(void)mode;
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(fs);
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
|
|
||||||
@ -181,6 +229,7 @@ spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs
|
|||||||
}
|
}
|
||||||
|
|
||||||
spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode mode) {
|
spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode mode) {
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(fs);
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
|
|
||||||
@ -209,7 +258,8 @@ spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_fl
|
|||||||
return fd->file_nbr;
|
return fd->file_nbr;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, u32_t len) {
|
s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(fs);
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
|
|
||||||
@ -277,7 +327,8 @@ static s32_t spiffs_hydro_write(spiffs *fs, spiffs_fd *fd, void *buf, u32_t offs
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len) {
|
s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(fs);
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
|
|
||||||
@ -314,8 +365,6 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SPIFFS_DBG("SPIFFS_write %d %04x offs:%d len %d\n", fh, fd->obj_id, offset, len);
|
|
||||||
|
|
||||||
#if SPIFFS_CACHE_WR
|
#if SPIFFS_CACHE_WR
|
||||||
if ((fd->flags & SPIFFS_DIRECT) == 0) {
|
if ((fd->flags & SPIFFS_DIRECT) == 0) {
|
||||||
if (len < (s32_t)SPIFFS_CFG_LOG_PAGE_SZ(fs)) {
|
if (len < (s32_t)SPIFFS_CFG_LOG_PAGE_SZ(fs)) {
|
||||||
@ -328,12 +377,13 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len) {
|
|||||||
offset + len > fd->cache_page->offset + SPIFFS_CFG_LOG_PAGE_SZ(fs)) // writing beyond cache page
|
offset + len > fd->cache_page->offset + SPIFFS_CFG_LOG_PAGE_SZ(fs)) // writing beyond cache page
|
||||||
{
|
{
|
||||||
// boundary violation, write back cache first and allocate new
|
// boundary violation, write back cache first and allocate new
|
||||||
SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page %d for fd %d:&04x, boundary viol, offs:%d size:%d\n",
|
SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page %d for fd %d:%04x, boundary viol, offs:%d size:%d\n",
|
||||||
fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->offset, fd->cache_page->size);
|
fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->offset, fd->cache_page->size);
|
||||||
res = spiffs_hydro_write(fs, fd,
|
res = spiffs_hydro_write(fs, fd,
|
||||||
spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
|
spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
|
||||||
fd->cache_page->offset, fd->cache_page->size);
|
fd->cache_page->offset, fd->cache_page->size);
|
||||||
spiffs_cache_fd_release(fs, fd->cache_page);
|
spiffs_cache_fd_release(fs, fd->cache_page);
|
||||||
|
SPIFFS_API_CHECK_RES(fs, res);
|
||||||
} else {
|
} else {
|
||||||
// writing within cache
|
// writing within cache
|
||||||
alloc_cpage = 0;
|
alloc_cpage = 0;
|
||||||
@ -379,6 +429,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len) {
|
|||||||
spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
|
spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
|
||||||
fd->cache_page->offset, fd->cache_page->size);
|
fd->cache_page->offset, fd->cache_page->size);
|
||||||
spiffs_cache_fd_release(fs, fd->cache_page);
|
spiffs_cache_fd_release(fs, fd->cache_page);
|
||||||
|
SPIFFS_API_CHECK_RES(fs, res);
|
||||||
res = spiffs_hydro_write(fs, fd, buf, offset, len);
|
res = spiffs_hydro_write(fs, fd, buf, offset, len);
|
||||||
SPIFFS_API_CHECK_RES(fs, res);
|
SPIFFS_API_CHECK_RES(fs, res);
|
||||||
}
|
}
|
||||||
@ -396,6 +447,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
|
s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(fs);
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
|
|
||||||
@ -439,7 +491,8 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32_t SPIFFS_remove(spiffs *fs, const char *path) {
|
s32_t SPIFFS_remove(spiffs *fs, char *path) {
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(fs);
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
|
|
||||||
@ -473,6 +526,7 @@ s32_t SPIFFS_remove(spiffs *fs, const char *path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) {
|
s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) {
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(fs);
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
|
|
||||||
@ -520,7 +574,8 @@ static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spi
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s) {
|
s32_t SPIFFS_stat(spiffs *fs, char *path, spiffs_stat *s) {
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(fs);
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
|
|
||||||
@ -538,6 +593,7 @@ s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) {
|
s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) {
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(fs);
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
|
|
||||||
@ -580,7 +636,7 @@ static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
|
|||||||
spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
|
spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
|
||||||
fd->cache_page->offset, fd->cache_page->size);
|
fd->cache_page->offset, fd->cache_page->size);
|
||||||
if (res < SPIFFS_OK) {
|
if (res < SPIFFS_OK) {
|
||||||
fs->errno = res;
|
fs->err_code = res;
|
||||||
}
|
}
|
||||||
spiffs_cache_fd_release(fs, fd->cache_page);
|
spiffs_cache_fd_release(fs, fd->cache_page);
|
||||||
}
|
}
|
||||||
@ -591,6 +647,7 @@ static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
|
s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(fs);
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
s32_t res = SPIFFS_OK;
|
s32_t res = SPIFFS_OK;
|
||||||
#if SPIFFS_CACHE_WR
|
#if SPIFFS_CACHE_WR
|
||||||
@ -604,8 +661,13 @@ s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SPIFFS_close(spiffs *fs, spiffs_file fh) {
|
void SPIFFS_close(spiffs *fs, spiffs_file fh) {
|
||||||
|
if (!SPIFFS_CHECK_CFG((fs))) {
|
||||||
|
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!SPIFFS_CHECK_MOUNT(fs)) {
|
if (!SPIFFS_CHECK_MOUNT(fs)) {
|
||||||
fs->errno = SPIFFS_ERR_NOT_MOUNTED;
|
fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
@ -618,7 +680,8 @@ void SPIFFS_close(spiffs *fs, spiffs_file fh) {
|
|||||||
SPIFFS_UNLOCK(fs);
|
SPIFFS_UNLOCK(fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newname) {
|
s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(fs);
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
|
|
||||||
@ -628,7 +691,7 @@ s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newname) {
|
|||||||
s32_t res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)old, &pix_old);
|
s32_t res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)old, &pix_old);
|
||||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||||
|
|
||||||
res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)newname, &pix_dummy);
|
res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)new, &pix_dummy);
|
||||||
if (res == SPIFFS_ERR_NOT_FOUND) {
|
if (res == SPIFFS_ERR_NOT_FOUND) {
|
||||||
res = SPIFFS_OK;
|
res = SPIFFS_OK;
|
||||||
} else if (res == SPIFFS_OK) {
|
} else if (res == SPIFFS_OK) {
|
||||||
@ -645,7 +708,7 @@ s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newname) {
|
|||||||
}
|
}
|
||||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||||
|
|
||||||
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, (u8_t*)newname,
|
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, (u8_t*)new,
|
||||||
0, &pix_dummy);
|
0, &pix_dummy);
|
||||||
|
|
||||||
if (res != SPIFFS_OK) {
|
if (res != SPIFFS_OK) {
|
||||||
@ -658,12 +721,19 @@ s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newname) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d) {
|
spiffs_DIR *SPIFFS_opendir(spiffs *fs, char *name, spiffs_DIR *d) {
|
||||||
(void)name;
|
(void)name;
|
||||||
if (!SPIFFS_CHECK_MOUNT(fs)) {
|
|
||||||
fs->errno = SPIFFS_ERR_NOT_MOUNTED;
|
if (!SPIFFS_CHECK_CFG((fs))) {
|
||||||
|
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!SPIFFS_CHECK_MOUNT(fs)) {
|
||||||
|
fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
d->fs = fs;
|
d->fs = fs;
|
||||||
d->block = 0;
|
d->block = 0;
|
||||||
d->entry = 0;
|
d->entry = 0;
|
||||||
@ -707,7 +777,7 @@ static s32_t spiffs_read_dir_v(
|
|||||||
|
|
||||||
struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) {
|
struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) {
|
||||||
if (!SPIFFS_CHECK_MOUNT(d->fs)) {
|
if (!SPIFFS_CHECK_MOUNT(d->fs)) {
|
||||||
d->fs->errno = SPIFFS_ERR_NOT_MOUNTED;
|
d->fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
@ -732,19 +802,21 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) {
|
|||||||
d->entry = entry + 1;
|
d->entry = entry + 1;
|
||||||
ret = e;
|
ret = e;
|
||||||
} else {
|
} else {
|
||||||
d->fs->errno = res;
|
d->fs->err_code = res;
|
||||||
}
|
}
|
||||||
SPIFFS_UNLOCK(fs);
|
SPIFFS_UNLOCK(fs);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32_t SPIFFS_closedir(spiffs_DIR *d) {
|
s32_t SPIFFS_closedir(spiffs_DIR *d) {
|
||||||
|
SPIFFS_API_CHECK_CFG(d->fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(d->fs);
|
SPIFFS_API_CHECK_MOUNT(d->fs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32_t SPIFFS_check(spiffs *fs) {
|
s32_t SPIFFS_check(spiffs *fs) {
|
||||||
s32_t res;
|
s32_t res;
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(fs);
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
|
|
||||||
@ -760,7 +832,32 @@ s32_t SPIFFS_check(spiffs *fs) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) {
|
||||||
|
s32_t res = SPIFFS_OK;
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
|
SPIFFS_LOCK(fs);
|
||||||
|
|
||||||
|
u32_t pages_per_block = SPIFFS_PAGES_PER_BLOCK(fs);
|
||||||
|
u32_t blocks = fs->block_count;
|
||||||
|
u32_t obj_lu_pages = SPIFFS_OBJ_LOOKUP_PAGES(fs);
|
||||||
|
u32_t data_page_size = SPIFFS_DATA_PAGE_SIZE(fs);
|
||||||
|
u32_t total_data_pages = (blocks - 2) * (pages_per_block - obj_lu_pages) + 1; // -2 for spare blocks, +1 for emergency page
|
||||||
|
|
||||||
|
if (total) {
|
||||||
|
*total = total_data_pages * data_page_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (used) {
|
||||||
|
*used = fs->stats_p_allocated * data_page_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIFFS_UNLOCK(fs);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) {
|
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) {
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(fs);
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
|
|
||||||
@ -780,6 +877,7 @@ s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) {
|
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) {
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(fs);
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
|
|
||||||
@ -801,6 +899,7 @@ s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) {
|
|||||||
#if SPIFFS_TEST_VISUALISATION
|
#if SPIFFS_TEST_VISUALISATION
|
||||||
s32_t SPIFFS_vis(spiffs *fs) {
|
s32_t SPIFFS_vis(spiffs *fs) {
|
||||||
s32_t res = SPIFFS_OK;
|
s32_t res = SPIFFS_OK;
|
||||||
|
SPIFFS_API_CHECK_CFG(fs);
|
||||||
SPIFFS_API_CHECK_MOUNT(fs);
|
SPIFFS_API_CHECK_MOUNT(fs);
|
||||||
SPIFFS_LOCK(fs);
|
SPIFFS_LOCK(fs);
|
||||||
|
|
||||||
@ -859,11 +958,14 @@ s32_t SPIFFS_vis(spiffs *fs) {
|
|||||||
} // per block
|
} // per block
|
||||||
|
|
||||||
spiffs_printf("era_cnt_max: %d\n", fs->max_erase_count);
|
spiffs_printf("era_cnt_max: %d\n", fs->max_erase_count);
|
||||||
spiffs_printf("last_errno: %d\n", fs->errno);
|
spiffs_printf("last_errno: %d\n", fs->err_code);
|
||||||
spiffs_printf("blocks: %d\n", fs->block_count);
|
spiffs_printf("blocks: %d\n", fs->block_count);
|
||||||
spiffs_printf("free_blocks: %d\n", fs->free_blocks);
|
spiffs_printf("free_blocks: %d\n", fs->free_blocks);
|
||||||
spiffs_printf("page_alloc: %d\n", fs->stats_p_allocated);
|
spiffs_printf("page_alloc: %d\n", fs->stats_p_allocated);
|
||||||
spiffs_printf("page_delet: %d\n", fs->stats_p_deleted);
|
spiffs_printf("page_delet: %d\n", fs->stats_p_deleted);
|
||||||
|
u32_t total, used;
|
||||||
|
SPIFFS_info(fs, &total, &used);
|
||||||
|
spiffs_printf("used: %d of %d\n", used, total);
|
||||||
|
|
||||||
SPIFFS_UNLOCK(fs);
|
SPIFFS_UNLOCK(fs);
|
||||||
return res;
|
return res;
|
||||||
|
170
cores/esp8266/spiffs/spiffs_nucleus.c
Executable file → Normal file
170
cores/esp8266/spiffs/spiffs_nucleus.c
Executable file → Normal file
@ -142,9 +142,13 @@ s32_t spiffs_obj_lu_find_entry_visitor(
|
|||||||
cur_block++;
|
cur_block++;
|
||||||
cur_block_addr = cur_block * SPIFFS_CFG_LOG_BLOCK_SZ(fs);
|
cur_block_addr = cur_block * SPIFFS_CFG_LOG_BLOCK_SZ(fs);
|
||||||
if (cur_block >= fs->block_count) {
|
if (cur_block >= fs->block_count) {
|
||||||
// block wrap
|
if (flags & SPIFFS_VIS_NO_WRAP) {
|
||||||
cur_block = 0;
|
return SPIFFS_VIS_END;
|
||||||
cur_block_addr = 0;
|
} else {
|
||||||
|
// block wrap
|
||||||
|
cur_block = 0;
|
||||||
|
cur_block_addr = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,6 +217,45 @@ s32_t spiffs_obj_lu_find_entry_visitor(
|
|||||||
return SPIFFS_VIS_END;
|
return SPIFFS_VIS_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s32_t spiffs_erase_block(
|
||||||
|
spiffs *fs,
|
||||||
|
spiffs_block_ix bix) {
|
||||||
|
s32_t res;
|
||||||
|
u32_t addr = SPIFFS_BLOCK_TO_PADDR(fs, bix);
|
||||||
|
s32_t size = SPIFFS_CFG_LOG_BLOCK_SZ(fs);
|
||||||
|
|
||||||
|
// here we ignore res, just try erasing the block
|
||||||
|
while (size > 0) {
|
||||||
|
SPIFFS_DBG("erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
||||||
|
(void)fs->cfg.hal_erase_f(addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
||||||
|
addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs);
|
||||||
|
size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs);
|
||||||
|
}
|
||||||
|
fs->free_blocks++;
|
||||||
|
|
||||||
|
// register erase count for this block
|
||||||
|
res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
|
||||||
|
SPIFFS_ERASE_COUNT_PADDR(fs, bix),
|
||||||
|
sizeof(spiffs_obj_id), (u8_t *)&fs->max_erase_count);
|
||||||
|
SPIFFS_CHECK_RES(res);
|
||||||
|
|
||||||
|
#if SPIFFS_USE_MAGIC
|
||||||
|
// finally, write magic
|
||||||
|
spiffs_obj_id magic = SPIFFS_MAGIC(fs);
|
||||||
|
res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
|
||||||
|
SPIFFS_MAGIC_PADDR(fs, bix),
|
||||||
|
sizeof(spiffs_obj_id), (u8_t *)&magic);
|
||||||
|
SPIFFS_CHECK_RES(res);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fs->max_erase_count++;
|
||||||
|
if (fs->max_erase_count == SPIFFS_OBJ_ID_IX_FLAG) {
|
||||||
|
fs->max_erase_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static s32_t spiffs_obj_lu_scan_v(
|
static s32_t spiffs_obj_lu_scan_v(
|
||||||
spiffs *fs,
|
spiffs *fs,
|
||||||
@ -238,40 +281,44 @@ static s32_t spiffs_obj_lu_scan_v(
|
|||||||
return SPIFFS_VIS_COUNTINUE;
|
return SPIFFS_VIS_COUNTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Scans thru all obj lu and counts free, deleted and used pages
|
// Scans thru all obj lu and counts free, deleted and used pages
|
||||||
// Find the maximum block erase count
|
// Find the maximum block erase count
|
||||||
|
// Checks magic if enabled
|
||||||
s32_t spiffs_obj_lu_scan(
|
s32_t spiffs_obj_lu_scan(
|
||||||
spiffs *fs) {
|
spiffs *fs) {
|
||||||
s32_t res;
|
s32_t res;
|
||||||
spiffs_block_ix bix;
|
spiffs_block_ix bix;
|
||||||
int entry;
|
int entry;
|
||||||
|
#if SPIFFS_USE_MAGIC
|
||||||
|
spiffs_block_ix unerased_bix = (spiffs_block_ix)-1;
|
||||||
|
#endif
|
||||||
|
|
||||||
fs->free_blocks = 0;
|
// find out erase count
|
||||||
fs->stats_p_allocated = 0;
|
// if enabled, check magic
|
||||||
fs->stats_p_deleted = 0;
|
|
||||||
|
|
||||||
res = spiffs_obj_lu_find_entry_visitor(fs,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
spiffs_obj_lu_scan_v,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
&bix,
|
|
||||||
&entry);
|
|
||||||
|
|
||||||
if (res == SPIFFS_VIS_END) {
|
|
||||||
res = SPIFFS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
SPIFFS_CHECK_RES(res);
|
|
||||||
|
|
||||||
bix = 0;
|
bix = 0;
|
||||||
spiffs_obj_id erase_count_final;
|
spiffs_obj_id erase_count_final;
|
||||||
spiffs_obj_id erase_count_min = SPIFFS_OBJ_ID_FREE;
|
spiffs_obj_id erase_count_min = SPIFFS_OBJ_ID_FREE;
|
||||||
spiffs_obj_id erase_count_max = 0;
|
spiffs_obj_id erase_count_max = 0;
|
||||||
while (bix < fs->block_count) {
|
while (bix < fs->block_count) {
|
||||||
|
#if SPIFFS_USE_MAGIC
|
||||||
|
spiffs_obj_id magic;
|
||||||
|
res = _spiffs_rd(fs,
|
||||||
|
SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||||
|
0, SPIFFS_MAGIC_PADDR(fs, bix) ,
|
||||||
|
sizeof(spiffs_obj_id), (u8_t *)&magic);
|
||||||
|
|
||||||
|
SPIFFS_CHECK_RES(res);
|
||||||
|
if (magic != SPIFFS_MAGIC(fs)) {
|
||||||
|
if (unerased_bix == (spiffs_block_ix)-1) {
|
||||||
|
// allow one unerased block as it might be powered down during an erase
|
||||||
|
unerased_bix = bix;
|
||||||
|
} else {
|
||||||
|
// more than one unerased block, bail out
|
||||||
|
SPIFFS_CHECK_RES(SPIFFS_ERR_NOT_A_FS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
spiffs_obj_id erase_count;
|
spiffs_obj_id erase_count;
|
||||||
res = _spiffs_rd(fs,
|
res = _spiffs_rd(fs,
|
||||||
SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||||
@ -297,6 +344,38 @@ s32_t spiffs_obj_lu_scan(
|
|||||||
|
|
||||||
fs->max_erase_count = erase_count_final;
|
fs->max_erase_count = erase_count_final;
|
||||||
|
|
||||||
|
#if SPIFFS_USE_MAGIC
|
||||||
|
if (unerased_bix != (spiffs_block_ix)-1) {
|
||||||
|
// found one unerased block, remedy
|
||||||
|
SPIFFS_DBG("mount: erase block %d\n", bix);
|
||||||
|
res = spiffs_erase_block(fs, unerased_bix);
|
||||||
|
SPIFFS_CHECK_RES(res);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// count blocks
|
||||||
|
|
||||||
|
fs->free_blocks = 0;
|
||||||
|
fs->stats_p_allocated = 0;
|
||||||
|
fs->stats_p_deleted = 0;
|
||||||
|
|
||||||
|
res = spiffs_obj_lu_find_entry_visitor(fs,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
spiffs_obj_lu_scan_v,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
&bix,
|
||||||
|
&entry);
|
||||||
|
|
||||||
|
if (res == SPIFFS_VIS_END) {
|
||||||
|
res = SPIFFS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIFFS_CHECK_RES(res);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -614,7 +693,7 @@ s32_t spiffs_object_create(
|
|||||||
spiffs_page_object_ix_header oix_hdr;
|
spiffs_page_object_ix_header oix_hdr;
|
||||||
int entry;
|
int entry;
|
||||||
|
|
||||||
res = spiffs_gc_check(fs, 0);
|
res = spiffs_gc_check(fs, SPIFFS_DATA_PAGE_SIZE(fs));
|
||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
|
|
||||||
obj_id |= SPIFFS_OBJ_ID_IX_FLAG;
|
obj_id |= SPIFFS_OBJ_ID_IX_FLAG;
|
||||||
@ -811,7 +890,17 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
|||||||
s32_t res = SPIFFS_OK;
|
s32_t res = SPIFFS_OK;
|
||||||
u32_t written = 0;
|
u32_t written = 0;
|
||||||
|
|
||||||
res = spiffs_gc_check(fs, len);
|
SPIFFS_DBG("append: %d bytes @ offs %d of size %d\n", len, offset, fd->size);
|
||||||
|
|
||||||
|
if (offset > fd->size) {
|
||||||
|
SPIFFS_DBG("append: offset reversed to size\n");
|
||||||
|
offset = fd->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = spiffs_gc_check(fs, len + SPIFFS_DATA_PAGE_SIZE(fs)); // add an extra page of data worth for meta
|
||||||
|
if (res != SPIFFS_OK) {
|
||||||
|
SPIFFS_DBG("append: gc check fail %d\n", res);
|
||||||
|
}
|
||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
|
|
||||||
spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
|
spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
|
||||||
@ -912,7 +1001,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
|||||||
res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &pix);
|
res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &pix);
|
||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
}
|
}
|
||||||
SPIFFS_DBG("append: %04x found object index at page %04x\n", fd->obj_id, pix);
|
SPIFFS_DBG("append: %04x found object index at page %04x [fd size %d]\n", fd->obj_id, pix, fd->size);
|
||||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
|
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
|
||||||
fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
|
fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
|
||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
@ -1003,8 +1092,8 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
|||||||
// update size in object header index page
|
// update size in object header index page
|
||||||
res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||||
fd->objix_hdr_pix, 0, 0, offset+written, &new_objix_hdr_page);
|
fd->objix_hdr_pix, 0, 0, offset+written, &new_objix_hdr_page);
|
||||||
SPIFFS_DBG("append: %04x store new size II %d in objix_hdr, %04x:%04x, written %d\n", fd->obj_id
|
SPIFFS_DBG("append: %04x store new size II %d in objix_hdr, %04x:%04x, written %d, res %d\n", fd->obj_id
|
||||||
, offset+written, new_objix_hdr_page, 0, written);
|
, offset+written, new_objix_hdr_page, 0, written, res2);
|
||||||
SPIFFS_CHECK_RES(res2);
|
SPIFFS_CHECK_RES(res2);
|
||||||
} else {
|
} else {
|
||||||
// wrote within object index header page
|
// wrote within object index header page
|
||||||
@ -1042,7 +1131,7 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
|||||||
s32_t res = SPIFFS_OK;
|
s32_t res = SPIFFS_OK;
|
||||||
u32_t written = 0;
|
u32_t written = 0;
|
||||||
|
|
||||||
res = spiffs_gc_check(fs, len);
|
res = spiffs_gc_check(fs, len + SPIFFS_DATA_PAGE_SIZE(fs));
|
||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
|
|
||||||
spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
|
spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
|
||||||
@ -1308,7 +1397,7 @@ s32_t spiffs_object_truncate(
|
|||||||
s32_t res = SPIFFS_OK;
|
s32_t res = SPIFFS_OK;
|
||||||
spiffs *fs = fd->fs;
|
spiffs *fs = fd->fs;
|
||||||
|
|
||||||
res = spiffs_gc_check(fs, 0);
|
res = spiffs_gc_check(fs, remove ? 0 : SPIFFS_DATA_PAGE_SIZE(fs));
|
||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
|
|
||||||
spiffs_page_ix objix_pix = fd->objix_hdr_pix;
|
spiffs_page_ix objix_pix = fd->objix_hdr_pix;
|
||||||
@ -1386,13 +1475,26 @@ s32_t spiffs_object_truncate(
|
|||||||
((spiffs_page_ix*)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = SPIFFS_OBJ_ID_FREE;
|
((spiffs_page_ix*)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = SPIFFS_OBJ_ID_FREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPIFFS_DBG("truncate: got data pix %04x\n", data_pix);
|
||||||
|
|
||||||
if (cur_size - SPIFFS_DATA_PAGE_SIZE(fs) >= new_size) {
|
if (cur_size - SPIFFS_DATA_PAGE_SIZE(fs) >= new_size) {
|
||||||
// delete full data page
|
// delete full data page
|
||||||
res = spiffs_page_data_check(fs, fd, data_pix, data_spix);
|
res = spiffs_page_data_check(fs, fd, data_pix, data_spix);
|
||||||
if (res != SPIFFS_OK) break;
|
if (res != SPIFFS_ERR_DELETED && res != SPIFFS_OK && res != SPIFFS_ERR_INDEX_REF_FREE) {
|
||||||
|
SPIFFS_DBG("truncate: err validating data pix %d\n", res);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == SPIFFS_OK) {
|
||||||
|
res = spiffs_page_delete(fs, data_pix);
|
||||||
|
if (res != SPIFFS_OK) {
|
||||||
|
SPIFFS_DBG("truncate: err deleting data pix %d\n", res);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (res == SPIFFS_ERR_DELETED || res == SPIFFS_ERR_INDEX_REF_FREE) {
|
||||||
|
res = SPIFFS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
res = spiffs_page_delete(fs, data_pix);
|
|
||||||
if (res != SPIFFS_OK) break;
|
|
||||||
// update current size
|
// update current size
|
||||||
if (cur_size % SPIFFS_DATA_PAGE_SIZE(fs) == 0) {
|
if (cur_size % SPIFFS_DATA_PAGE_SIZE(fs) == 0) {
|
||||||
cur_size -= SPIFFS_DATA_PAGE_SIZE(fs);
|
cur_size -= SPIFFS_DATA_PAGE_SIZE(fs);
|
||||||
|
49
cores/esp8266/spiffs/spiffs_nucleus.h
Executable file → Normal file
49
cores/esp8266/spiffs/spiffs_nucleus.h
Executable file → Normal file
@ -131,6 +131,10 @@
|
|||||||
#define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
|
#define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
|
||||||
#define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
|
#define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
|
||||||
|
|
||||||
|
#define SPIFFS_MAGIC(fs) ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
|
||||||
|
|
||||||
|
#define SPIFFS_CONFIG_MAGIC (0x20090315)
|
||||||
|
|
||||||
#if SPIFFS_SINGLETON == 0
|
#if SPIFFS_SINGLETON == 0
|
||||||
#define SPIFFS_CFG_LOG_PAGE_SZ(fs) \
|
#define SPIFFS_CFG_LOG_PAGE_SZ(fs) \
|
||||||
((fs)->cfg.log_page_size)
|
((fs)->cfg.log_page_size)
|
||||||
@ -189,9 +193,18 @@
|
|||||||
// returns data size in a data page
|
// returns data size in a data page
|
||||||
#define SPIFFS_DATA_PAGE_SIZE(fs) \
|
#define SPIFFS_DATA_PAGE_SIZE(fs) \
|
||||||
( SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header) )
|
( SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header) )
|
||||||
// returns physical address for block's erase count
|
// returns physical address for block's erase count,
|
||||||
|
// always in the physical last entry of the last object lookup page
|
||||||
#define SPIFFS_ERASE_COUNT_PADDR(fs, bix) \
|
#define SPIFFS_ERASE_COUNT_PADDR(fs, bix) \
|
||||||
( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id) )
|
( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id) )
|
||||||
|
// returns physical address for block's magic,
|
||||||
|
// always in the physical second last entry of the last object lookup page
|
||||||
|
#define SPIFFS_MAGIC_PADDR(fs, bix) \
|
||||||
|
( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id)*2 )
|
||||||
|
// checks if there is any room for magic in the object luts
|
||||||
|
#define SPIFFS_CHECK_MAGIC_POSSIBLE(fs) \
|
||||||
|
( (SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) % (SPIFFS_CFG_LOG_PAGE_SZ(fs)/sizeof(spiffs_obj_id))) * sizeof(spiffs_obj_id) \
|
||||||
|
<= (SPIFFS_CFG_LOG_PAGE_SZ(fs)-sizeof(spiffs_obj_id)*2) )
|
||||||
|
|
||||||
// define helpers object
|
// define helpers object
|
||||||
|
|
||||||
@ -238,7 +251,10 @@
|
|||||||
|
|
||||||
|
|
||||||
#define SPIFFS_CHECK_MOUNT(fs) \
|
#define SPIFFS_CHECK_MOUNT(fs) \
|
||||||
((fs)->block_count > 0)
|
((fs)->mounted != 0)
|
||||||
|
|
||||||
|
#define SPIFFS_CHECK_CFG(fs) \
|
||||||
|
((fs)->config_magic == SPIFFS_CONFIG_MAGIC)
|
||||||
|
|
||||||
#define SPIFFS_CHECK_RES(res) \
|
#define SPIFFS_CHECK_RES(res) \
|
||||||
do { \
|
do { \
|
||||||
@ -247,19 +263,25 @@
|
|||||||
|
|
||||||
#define SPIFFS_API_CHECK_MOUNT(fs) \
|
#define SPIFFS_API_CHECK_MOUNT(fs) \
|
||||||
if (!SPIFFS_CHECK_MOUNT((fs))) { \
|
if (!SPIFFS_CHECK_MOUNT((fs))) { \
|
||||||
(fs)->errno = SPIFFS_ERR_NOT_MOUNTED; \
|
(fs)->err_code = SPIFFS_ERR_NOT_MOUNTED; \
|
||||||
|
return -1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SPIFFS_API_CHECK_CFG(fs) \
|
||||||
|
if (!SPIFFS_CHECK_CFG((fs))) { \
|
||||||
|
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \
|
||||||
return -1; \
|
return -1; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SPIFFS_API_CHECK_RES(fs, res) \
|
#define SPIFFS_API_CHECK_RES(fs, res) \
|
||||||
if ((res) < SPIFFS_OK) { \
|
if ((res) < SPIFFS_OK) { \
|
||||||
(fs)->errno = (res); \
|
(fs)->err_code = (res); \
|
||||||
return -1; \
|
return -1; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \
|
#define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \
|
||||||
if ((res) < SPIFFS_OK) { \
|
if ((res) < SPIFFS_OK) { \
|
||||||
(fs)->errno = (res); \
|
(fs)->err_code = (res); \
|
||||||
SPIFFS_UNLOCK(fs); \
|
SPIFFS_UNLOCK(fs); \
|
||||||
return -1; \
|
return -1; \
|
||||||
}
|
}
|
||||||
@ -381,6 +403,8 @@ typedef struct {
|
|||||||
// object structs
|
// object structs
|
||||||
|
|
||||||
// page header, part of each page except object lookup pages
|
// page header, part of each page except object lookup pages
|
||||||
|
// NB: this is always aligned when the data page is an object index,
|
||||||
|
// as in this case struct spiffs_page_object_ix is used
|
||||||
typedef struct __attribute(( packed )) {
|
typedef struct __attribute(( packed )) {
|
||||||
// object id
|
// object id
|
||||||
spiffs_obj_id obj_id;
|
spiffs_obj_id obj_id;
|
||||||
@ -391,7 +415,11 @@ typedef struct __attribute(( packed )) {
|
|||||||
} spiffs_page_header;
|
} spiffs_page_header;
|
||||||
|
|
||||||
// object index header page header
|
// object index header page header
|
||||||
typedef struct __attribute(( packed )) {
|
typedef struct __attribute(( packed ))
|
||||||
|
#if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
|
||||||
|
__attribute(( aligned(sizeof(spiffs_page_ix)) ))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
// common page header
|
// common page header
|
||||||
spiffs_page_header p_hdr;
|
spiffs_page_header p_hdr;
|
||||||
// alignment
|
// alignment
|
||||||
@ -400,8 +428,6 @@ typedef struct __attribute(( packed )) {
|
|||||||
u32_t size;
|
u32_t size;
|
||||||
// type of object
|
// type of object
|
||||||
spiffs_obj_type type;
|
spiffs_obj_type type;
|
||||||
// alignment2
|
|
||||||
u8_t _align2[4 - (sizeof(spiffs_obj_type)&3)==0 ? 4 : (sizeof(spiffs_obj_type)&3)];
|
|
||||||
// name of object
|
// name of object
|
||||||
u8_t name[SPIFFS_OBJ_NAME_LEN];
|
u8_t name[SPIFFS_OBJ_NAME_LEN];
|
||||||
} spiffs_page_object_ix_header;
|
} spiffs_page_object_ix_header;
|
||||||
@ -480,6 +506,10 @@ s32_t spiffs_obj_lu_find_entry_visitor(
|
|||||||
spiffs_block_ix *block_ix,
|
spiffs_block_ix *block_ix,
|
||||||
int *lu_entry);
|
int *lu_entry);
|
||||||
|
|
||||||
|
s32_t spiffs_erase_block(
|
||||||
|
spiffs *fs,
|
||||||
|
spiffs_block_ix bix);
|
||||||
|
|
||||||
// ---------------
|
// ---------------
|
||||||
|
|
||||||
s32_t spiffs_obj_lu_scan(
|
s32_t spiffs_obj_lu_scan(
|
||||||
@ -627,7 +657,8 @@ s32_t spiffs_gc_erase_page_stats(
|
|||||||
s32_t spiffs_gc_find_candidate(
|
s32_t spiffs_gc_find_candidate(
|
||||||
spiffs *fs,
|
spiffs *fs,
|
||||||
spiffs_block_ix **block_candidate,
|
spiffs_block_ix **block_candidate,
|
||||||
int *candidate_count);
|
int *candidate_count,
|
||||||
|
char fs_crammed);
|
||||||
|
|
||||||
s32_t spiffs_gc_clean(
|
s32_t spiffs_gc_clean(
|
||||||
spiffs *fs,
|
spiffs *fs,
|
||||||
|
38
doc/exception_causes.md
Normal file
38
doc/exception_causes.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
Exception Causes (EXCCAUSE)
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
| EXC-CAUSE Code | Cause Name | Cause Description | Required Option | EXC-VADDR Loaded |
|
||||||
|
|:--------------:|:---------------------------|:------------------------------------------------------------------------------------------------------------|:-------------------------|:----------------:|
|
||||||
|
| 0 | IllegalInstructionCause | Illegal instruction | Exception | No |
|
||||||
|
| 1 | SyscallCause | SYSCALL instruction | Exception | No |
|
||||||
|
| 2 | InstructionFetchErrorCause | Processor internal physical address or data error during instruction fetch | Exception | Yes |
|
||||||
|
| 3 | LoadStoreErrorCause | Processor internal physical address or data error during load or store | Exception | Yes |
|
||||||
|
| 4 | Level1InterruptCause | Level-1 interrupt as indicated by set level-1 bits in the INTERRUPT register | Interrupt | No |
|
||||||
|
| 5 | AllocaCause | MOVSP instruction, if caller’s registers are not in the register file | Windowed Register | No |
|
||||||
|
| 6 | IntegerDivideByZeroCause | QUOS, QUOU, REMS, or REMU divisor operand is zero | 32-bit Integer Divide | No |
|
||||||
|
| 7 | Reserved for Tensilica | | | |
|
||||||
|
| 8 | PrivilegedCause | Attempt to execute a privileged operation when CRING ? 0 | MMU | No |
|
||||||
|
| 9 | LoadStoreAlignmentCause | Load or store to an unaligned address | Unaligned Exception | Yes |
|
||||||
|
| 10..11 | Reserved for Tensilica | | | |
|
||||||
|
| 12 | InstrPIFDataErrorCause | PIF data error during instruction fetch | Processor Interface | Yes |
|
||||||
|
| 13 | LoadStorePIFDataErrorCause | Synchronous PIF data error during LoadStore access | Processor Interface | Yes |
|
||||||
|
| 14 | InstrPIFAddrErrorCause | PIF address error during instruction fetch | Processor Interface | Yes |
|
||||||
|
| 15 | LoadStorePIFAddrErrorCause | Synchronous PIF address error during LoadStore access | Processor Interface | Yes |
|
||||||
|
| 16 | InstTLBMissCause | Error during Instruction TLB refill | MMU | Yes |
|
||||||
|
| 17 | InstTLBMultiHitCause | Multiple instruction TLB entries matched | MMU | Yes |
|
||||||
|
| 18 | InstFetchPrivilegeCause | An instruction fetch referenced a virtual address at a ring level less than CRING | MMU | Yes |
|
||||||
|
| 19 | Reserved for Tensilica | | | |
|
||||||
|
| 20 | InstFetchProhibitedCause | An instruction fetch referenced a page mapped with an attribute that does not permit instruction fetch | Region Protection or MMU | Yes |
|
||||||
|
| 21..23 | Reserved for Tensilica | | | |
|
||||||
|
| 24 | LoadStoreTLBMissCause | Error during TLB refill for a load or store | MMU | Yes |
|
||||||
|
| 25 | LoadStoreTLBMultiHitCause | Multiple TLB entries matched for a load or store | MMU | Yes |
|
||||||
|
| 26 | LoadStorePrivilegeCause | A load or store referenced a virtual address at a ring level less than CRING | MMU | Yes |
|
||||||
|
| 27 | Reserved for Tensilica | | | |
|
||||||
|
| 28 | LoadProhibitedCause | A load referenced a page mapped with an attribute that does not permit loads | Region Protection or MMU | Yes |
|
||||||
|
| 29 | StoreProhibitedCause | A store referenced a page mapped with an attribute that does not permit stores | Region Protection or MMU | Yes |
|
||||||
|
| 30..31 | Reserved for Tensilica | | | |
|
||||||
|
| 32..39 | CoprocessornDisabled | Coprocessor n instruction when cpn disabled. n varies 0..7 as the cause varies 32..39 | Coprocessor | No |
|
||||||
|
| 40..63 | Reserved | | | |
|
||||||
|
|
||||||
|
|
||||||
|
Infos from Xtensa Instruction Set Architecture (ISA) Reference Manual
|
@ -28,9 +28,10 @@
|
|||||||
#include "os_type.h"
|
#include "os_type.h"
|
||||||
#include "osapi.h"
|
#include "osapi.h"
|
||||||
#include "spi_flash.h"
|
#include "spi_flash.h"
|
||||||
|
extern uint32_t _SPIFFS_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CONFIG_START_SECTOR 0x7b
|
#define CONFIG_START_SECTOR (((uint32_t)_SPIFFS_end - 0x40200000) / 4096)
|
||||||
#define CONFIG_SECTOR (CONFIG_START_SECTOR + 0)
|
#define CONFIG_SECTOR (CONFIG_START_SECTOR + 0)
|
||||||
#define CONFIG_ADDR (SPI_FLASH_SEC_SIZE * CONFIG_SECTOR)
|
#define CONFIG_ADDR (SPI_FLASH_SEC_SIZE * CONFIG_SECTOR)
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ EEPROMClass::EEPROMClass()
|
|||||||
|
|
||||||
void EEPROMClass::begin(size_t size)
|
void EEPROMClass::begin(size_t size)
|
||||||
{
|
{
|
||||||
if (size < 0)
|
if (size <= 0)
|
||||||
return;
|
return;
|
||||||
if (size > SPI_FLASH_SEC_SIZE)
|
if (size > SPI_FLASH_SEC_SIZE)
|
||||||
size = SPI_FLASH_SEC_SIZE;
|
size = SPI_FLASH_SEC_SIZE;
|
||||||
@ -49,7 +50,9 @@ void EEPROMClass::begin(size_t size)
|
|||||||
_data = new uint8_t[size];
|
_data = new uint8_t[size];
|
||||||
_size = size;
|
_size = size;
|
||||||
|
|
||||||
|
noInterrupts();
|
||||||
spi_flash_read(CONFIG_ADDR, reinterpret_cast<uint32_t*>(_data), _size);
|
spi_flash_read(CONFIG_ADDR, reinterpret_cast<uint32_t*>(_data), _size);
|
||||||
|
interrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EEPROMClass::end()
|
void EEPROMClass::end()
|
||||||
@ -58,8 +61,9 @@ void EEPROMClass::end()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
commit();
|
commit();
|
||||||
|
if(_data) {
|
||||||
delete[] _data;
|
delete[] _data;
|
||||||
|
}
|
||||||
_data = 0;
|
_data = 0;
|
||||||
_size = 0;
|
_size = 0;
|
||||||
}
|
}
|
||||||
@ -69,6 +73,8 @@ uint8_t EEPROMClass::read(int address)
|
|||||||
{
|
{
|
||||||
if (address < 0 || (size_t)address >= _size)
|
if (address < 0 || (size_t)address >= _size)
|
||||||
return 0;
|
return 0;
|
||||||
|
if(!_data)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return _data[address];
|
return _data[address];
|
||||||
}
|
}
|
||||||
@ -77,6 +83,8 @@ void EEPROMClass::write(int address, uint8_t value)
|
|||||||
{
|
{
|
||||||
if (address < 0 || (size_t)address >= _size)
|
if (address < 0 || (size_t)address >= _size)
|
||||||
return;
|
return;
|
||||||
|
if(!_data)
|
||||||
|
return;
|
||||||
|
|
||||||
_data[address] = value;
|
_data[address] = value;
|
||||||
_dirty = true;
|
_dirty = true;
|
||||||
@ -89,20 +97,24 @@ bool EEPROMClass::commit()
|
|||||||
return false;
|
return false;
|
||||||
if(!_dirty)
|
if(!_dirty)
|
||||||
return true;
|
return true;
|
||||||
|
if(!_data)
|
||||||
|
return false;
|
||||||
|
|
||||||
ETS_UART_INTR_DISABLE();
|
noInterrupts();
|
||||||
if(spi_flash_erase_sector(CONFIG_SECTOR) == SPI_FLASH_RESULT_OK) {
|
if(spi_flash_erase_sector(CONFIG_SECTOR) == SPI_FLASH_RESULT_OK) {
|
||||||
if(spi_flash_write(CONFIG_ADDR, reinterpret_cast<uint32_t*>(_data), _size) == SPI_FLASH_RESULT_OK) {
|
if(spi_flash_write(CONFIG_ADDR, reinterpret_cast<uint32_t*>(_data), _size) == SPI_FLASH_RESULT_OK) {
|
||||||
_dirty = false;
|
_dirty = false;
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ETS_UART_INTR_ENABLE();
|
interrupts();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t * EEPROMClass::getDataPtr()
|
uint8_t * EEPROMClass::getDataPtr()
|
||||||
{
|
{
|
||||||
|
_dirty = true;
|
||||||
return &_data[0];
|
return &_data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +76,20 @@ public:
|
|||||||
|
|
||||||
void sendHeader(String name, String value, bool first = false);
|
void sendHeader(String name, String value, bool first = false);
|
||||||
void sendContent(String content);
|
void sendContent(String content);
|
||||||
|
|
||||||
|
template<typename T> size_t streamFile(T &file, String contentType){
|
||||||
|
String head = "HTTP/1.1 200 OK\r\nContent-Type: ";
|
||||||
|
head += contentType;
|
||||||
|
head += "\r\nContent-Length: ";
|
||||||
|
head += file.size();
|
||||||
|
head += "\r\nConnection: close";
|
||||||
|
head += "\r\nAccess-Control-Allow-Origin: *";
|
||||||
|
head += "\r\n\r\n";
|
||||||
|
_currentClient.print(head);
|
||||||
|
head = String();
|
||||||
|
return _currentClient.write(file, HTTP_DOWNLOAD_UNIT_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _handleRequest();
|
void _handleRequest();
|
||||||
bool _parseRequest(WiFiClient& client);
|
bool _parseRequest(WiFiClient& client);
|
||||||
|
33
libraries/ESP8266WiFi/examples/WiFiMulti/WiFiMulti.ino
Normal file
33
libraries/ESP8266WiFi/examples/WiFiMulti/WiFiMulti.ino
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* This sketch trys to Connect to the best AP based on a given list
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <ESP8266WiFiMulti.h>
|
||||||
|
|
||||||
|
ESP8266WiFiMulti WiFiMulti = ESP8266WiFiMulti();
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(10);
|
||||||
|
|
||||||
|
WiFiMulti.addAP("ssid_from_AP_1", "your_password_for_AP_1");
|
||||||
|
WiFiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2");
|
||||||
|
WiFiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3");
|
||||||
|
|
||||||
|
Serial.println("Connecting Wifi...");
|
||||||
|
if(wifiMulti.run() == WL_CONNECTED) {
|
||||||
|
Serial.println("");
|
||||||
|
Serial.println("WiFi connected");
|
||||||
|
Serial.println("IP address: ");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if(wifiMulti.run() != WL_CONNECTED) {
|
||||||
|
Serial.println("WiFi not connected!");
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
}
|
@ -81,6 +81,14 @@ int ESP8266WiFiClass::begin(const char* ssid, const char *passphrase)
|
|||||||
return status();
|
return status();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t ESP8266WiFiClass::waitForConnectResult(){
|
||||||
|
if ((wifi_get_opmode() & 1) == 0)//1 and 3 have STA enabled
|
||||||
|
return WL_DISCONNECTED;
|
||||||
|
while (status() == WL_DISCONNECTED)
|
||||||
|
delay(100);
|
||||||
|
return status();
|
||||||
|
}
|
||||||
|
|
||||||
void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet)
|
void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet)
|
||||||
{
|
{
|
||||||
struct ip_info info;
|
struct ip_info info;
|
||||||
@ -336,7 +344,7 @@ uint8_t ESP8266WiFiClass::encryptionType(uint8_t i)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ESP8266WiFiClass::status()
|
wl_status_t ESP8266WiFiClass::status()
|
||||||
{
|
{
|
||||||
int status = wifi_station_get_connect_status();
|
int status = wifi_station_get_connect_status();
|
||||||
|
|
||||||
|
@ -58,6 +58,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
int begin(const char* ssid, const char *passphrase);
|
int begin(const char* ssid, const char *passphrase);
|
||||||
|
|
||||||
|
/* Wait for Wifi connection to reach a result
|
||||||
|
* returns the status reached or disconnect if STA is off
|
||||||
|
*/
|
||||||
|
uint8_t waitForConnectResult();
|
||||||
|
|
||||||
/* Set up an open access point
|
/* Set up an open access point
|
||||||
*
|
*
|
||||||
@ -195,7 +199,7 @@ public:
|
|||||||
*
|
*
|
||||||
* return: one of the value defined in wl_status_t
|
* return: one of the value defined in wl_status_t
|
||||||
*/
|
*/
|
||||||
uint8_t status();
|
wl_status_t status();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Resolve the given hostname to an IP address.
|
* Resolve the given hostname to an IP address.
|
||||||
|
171
libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp
Normal file
171
libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @file ESP8266WiFiMulti.cpp
|
||||||
|
* @date 16.05.2015
|
||||||
|
* @author Markus Sattler
|
||||||
|
*
|
||||||
|
* 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 "ESP8266WiFiMulti.h"
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
ESP8266WiFiMulti::ESP8266WiFiMulti() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP8266WiFiMulti::~ESP8266WiFiMulti() {
|
||||||
|
APlistClean();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ESP8266WiFiMulti::addAP(const char* ssid, const char *passphrase) {
|
||||||
|
return APlistAdd(ssid, passphrase);
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_status_t ESP8266WiFiMulti::run(void) {
|
||||||
|
|
||||||
|
wl_status_t status = WiFi.status();
|
||||||
|
if(status == WL_DISCONNECTED || status == WL_NO_SSID_AVAIL || status == WL_IDLE_STATUS || status == WL_CONNECT_FAILED) {
|
||||||
|
|
||||||
|
WifiAPlist_t bestNetwork { NULL, NULL };
|
||||||
|
int bestNetworkDb = INT_MIN;
|
||||||
|
|
||||||
|
// WiFi.scanNetworks will return the number of networks found
|
||||||
|
int8_t n = WiFi.scanNetworks();
|
||||||
|
|
||||||
|
DEBUG_WIFI_MULTI("[WIFI] scan done\n");
|
||||||
|
delay(0);
|
||||||
|
|
||||||
|
if(n <= 0) {
|
||||||
|
DEBUG_WIFI_MULTI("[WIFI] no networks found\n");
|
||||||
|
} else {
|
||||||
|
DEBUG_WIFI_MULTI("[WIFI] %d networks found\n", n);
|
||||||
|
for(int8_t i = 0; i < n; ++i) {
|
||||||
|
const char * ssid_scan = WiFi.SSID(i);
|
||||||
|
int32_t rssi_scan = WiFi.RSSI(i);
|
||||||
|
uint8_t sec_scan = WiFi.encryptionType(i);
|
||||||
|
|
||||||
|
bool known = false;
|
||||||
|
for(uint32_t x = 0; x < APlist.size(); x++) {
|
||||||
|
WifiAPlist_t entry = APlist[x];
|
||||||
|
|
||||||
|
if(strcmp(entry.ssid, ssid_scan) == 0) { // SSID match
|
||||||
|
known = true;
|
||||||
|
if(rssi_scan > bestNetworkDb) { // best network
|
||||||
|
if(sec_scan == ENC_TYPE_NONE || entry.passphrase) { // check for passphrase if not open wlan
|
||||||
|
bestNetworkDb = rssi_scan;
|
||||||
|
memcpy((void*) &bestNetwork, (void*) &entry, sizeof(bestNetwork));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(known) {
|
||||||
|
DEBUG_WIFI_MULTI(" ---> ");
|
||||||
|
} else {
|
||||||
|
DEBUG_WIFI_MULTI(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_WIFI_MULTI(" %d: %s (%d) %c\n", i, ssid_scan, rssi_scan, (sec_scan == ENC_TYPE_NONE) ? ' ' : '*');
|
||||||
|
delay(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_WIFI_MULTI("\n\n");
|
||||||
|
delay(0);
|
||||||
|
|
||||||
|
if(bestNetwork.ssid) {
|
||||||
|
DEBUG_WIFI_MULTI("[WIFI] Connecting SSID: %s (%d)\n", bestNetwork.ssid, bestNetworkDb);
|
||||||
|
|
||||||
|
WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase);
|
||||||
|
status = WiFi.status();
|
||||||
|
|
||||||
|
// wait for connection or fail
|
||||||
|
while(status != WL_CONNECTED && status != WL_NO_SSID_AVAIL && status != WL_CONNECT_FAILED) {
|
||||||
|
delay(10);
|
||||||
|
status = WiFi.status();
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress ip;
|
||||||
|
switch(status) {
|
||||||
|
case WL_CONNECTED:
|
||||||
|
ip = WiFi.localIP();
|
||||||
|
DEBUG_WIFI_MULTI("[WIFI] Connecting done.\n");
|
||||||
|
DEBUG_WIFI_MULTI("[WIFI] SSID: %s\n", WiFi.SSID());
|
||||||
|
DEBUG_WIFI_MULTI("[WIFI] IP: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
|
||||||
|
break;
|
||||||
|
case WL_NO_SSID_AVAIL:
|
||||||
|
DEBUG_WIFI_MULTI("[WIFI] Connecting Faild AP not found.\n");
|
||||||
|
break;
|
||||||
|
case WL_CONNECT_FAILED:
|
||||||
|
DEBUG_WIFI_MULTI("[WIFI] Connecting Faild.\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DEBUG_WIFI_MULTI("[WIFI] Connecting Faild (%d).\n", status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DEBUG_WIFI_MULTI("[WIFI] no matching wifi found!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ##################################################################################
|
||||||
|
|
||||||
|
bool ESP8266WiFiMulti::APlistAdd(const char* ssid, const char *passphrase) {
|
||||||
|
|
||||||
|
WifiAPlist_t newAP;
|
||||||
|
|
||||||
|
newAP.ssid = (char*) malloc(strlen(ssid));
|
||||||
|
|
||||||
|
if(!newAP.ssid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(newAP.ssid, ssid);
|
||||||
|
|
||||||
|
if(passphrase && *passphrase != 0x00) {
|
||||||
|
newAP.passphrase = (char*) malloc(strlen(passphrase));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!newAP.passphrase) {
|
||||||
|
free(newAP.ssid);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(newAP.passphrase, passphrase);
|
||||||
|
|
||||||
|
APlist.push_back(newAP);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP8266WiFiMulti::APlistClean(void) {
|
||||||
|
for(uint32_t i = 0; i < APlist.size(); i++) {
|
||||||
|
WifiAPlist_t entry = APlist[i];
|
||||||
|
if(entry.ssid) {
|
||||||
|
free(entry.ssid);
|
||||||
|
}
|
||||||
|
if(entry.passphrase) {
|
||||||
|
free(entry.passphrase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
APlist.clear();
|
||||||
|
}
|
||||||
|
|
60
libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h
Normal file
60
libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @file ESP8266WiFiMulti.h
|
||||||
|
* @date 16.05.2015
|
||||||
|
* @author Markus Sattler
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef WIFICLIENTMULTI_H_
|
||||||
|
#define WIFICLIENTMULTI_H_
|
||||||
|
|
||||||
|
#include "ESP8266WiFi.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
//#define DEBUG_WIFI_MULTI(...) os_printf( __VA_ARGS__ )
|
||||||
|
|
||||||
|
#ifndef DEBUG_WIFI_MULTI
|
||||||
|
#define DEBUG_WIFI_MULTI(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char * ssid;
|
||||||
|
char * passphrase;
|
||||||
|
} WifiAPlist_t;
|
||||||
|
|
||||||
|
class ESP8266WiFiMulti {
|
||||||
|
public:
|
||||||
|
ESP8266WiFiMulti();
|
||||||
|
~ESP8266WiFiMulti();
|
||||||
|
|
||||||
|
bool addAP(const char* ssid, const char *passphrase = NULL);
|
||||||
|
|
||||||
|
wl_status_t run(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<WifiAPlist_t> APlist;
|
||||||
|
bool APlistAdd(const char* ssid, const char *passphrase = NULL);
|
||||||
|
void APlistClean(void);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* WIFICLIENTMULTI_H_ */
|
@ -48,14 +48,14 @@
|
|||||||
#define WL_MAX_ATTEMPT_CONNECTION 10
|
#define WL_MAX_ATTEMPT_CONNECTION 10
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library
|
WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library
|
||||||
WL_IDLE_STATUS = 0,
|
WL_IDLE_STATUS = 0,
|
||||||
WL_NO_SSID_AVAIL,
|
WL_NO_SSID_AVAIL = 1,
|
||||||
WL_SCAN_COMPLETED,
|
WL_SCAN_COMPLETED = 2,
|
||||||
WL_CONNECTED,
|
WL_CONNECTED = 3,
|
||||||
WL_CONNECT_FAILED,
|
WL_CONNECT_FAILED = 4,
|
||||||
WL_CONNECTION_LOST,
|
WL_CONNECTION_LOST = 5,
|
||||||
WL_DISCONNECTED
|
WL_DISCONNECTED = 6
|
||||||
} wl_status_t;
|
} wl_status_t;
|
||||||
|
|
||||||
/* Encryption modes */
|
/* Encryption modes */
|
||||||
|
@ -106,6 +106,14 @@ public:
|
|||||||
|
|
||||||
boolean rmdir(char *filepath);
|
boolean rmdir(char *filepath);
|
||||||
|
|
||||||
|
uint8_t type(){ return card.type(); }
|
||||||
|
uint8_t fatType(){ return volume.fatType(); }
|
||||||
|
size_t blocksPerCluster(){ return volume.blocksPerCluster(); }
|
||||||
|
size_t totalClusters(){ return volume.clusterCount(); }
|
||||||
|
size_t blockSize(){ return (size_t)0x200; }
|
||||||
|
size_t totalBlocks(){ return (totalClusters() / blocksPerCluster()); }
|
||||||
|
size_t clusterSize(){ return blocksPerCluster() * blockSize(); }
|
||||||
|
size_t size(){ return (clusterSize() * totalClusters()); }
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// This is used to determine the mode used to open a file
|
// This is used to determine the mode used to open a file
|
||||||
|
@ -121,14 +121,14 @@ void SPIClass::setBitOrder(uint8_t bitOrder) {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
static uint32_t ClkRegToFreq(spiClk_t * reg) {
|
static uint32_t ClkRegToFreq(spiClk_t * reg) {
|
||||||
return (F_CPU / ((reg->regPre + 1) * (reg->regN + 1)));
|
return (SPI_MAX_SPEED / ((reg->regPre + 1) * (reg->regN + 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPIClass::setFrequency(uint32_t freq) {
|
void SPIClass::setFrequency(uint32_t freq) {
|
||||||
static uint32_t lastSetFrequency = 0;
|
static uint32_t lastSetFrequency = 0;
|
||||||
static uint32_t lastSetRegister = 0;
|
static uint32_t lastSetRegister = 0;
|
||||||
|
|
||||||
if(freq >= F_CPU) {
|
if(freq >= SPI_MAX_SPEED) {
|
||||||
setClockDivider(0x80000000);
|
setClockDivider(0x80000000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -164,7 +164,7 @@ void SPIClass::setFrequency(uint32_t freq) {
|
|||||||
reg.regN = calN;
|
reg.regN = calN;
|
||||||
|
|
||||||
while(calPreVari++ <= 1) { // test different variants for Pre (we calculate in int so we miss the decimals, testing is the easyest and fastest way)
|
while(calPreVari++ <= 1) { // test different variants for Pre (we calculate in int so we miss the decimals, testing is the easyest and fastest way)
|
||||||
calPre = (((F_CPU / (reg.regN + 1)) / freq) - 1) + calPreVari;
|
calPre = (((SPI_MAX_SPEED / (reg.regN + 1)) / freq) - 1) + calPreVari;
|
||||||
if(calPre > 0x1FFF) {
|
if(calPre > 0x1FFF) {
|
||||||
reg.regPre = 0x1FFF; // 8191
|
reg.regPre = 0x1FFF; // 8191
|
||||||
} else if(calPre <= 0) {
|
} else if(calPre <= 0) {
|
||||||
|
@ -45,6 +45,8 @@
|
|||||||
#define SPI_CLOCK_DIV64 0x04fc1001 //250 KHz
|
#define SPI_CLOCK_DIV64 0x04fc1001 //250 KHz
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SPI_MAX_SPEED (80000000L)
|
||||||
|
|
||||||
const uint8_t SPI_MODE0 = 0x00; ///< CPOL: 0 CPHA: 0
|
const uint8_t SPI_MODE0 = 0x00; ///< CPOL: 0 CPHA: 0
|
||||||
const uint8_t SPI_MODE1 = 0x01; ///< CPOL: 0 CPHA: 1
|
const uint8_t SPI_MODE1 = 0x01; ///< CPOL: 0 CPHA: 1
|
||||||
const uint8_t SPI_MODE2 = 0x10; ///< CPOL: 1 CPHA: 0
|
const uint8_t SPI_MODE2 = 0x10; ///< CPOL: 1 CPHA: 0
|
||||||
|
@ -15,7 +15,7 @@ compiler.sdk.path={compiler.tools.path}sdk/
|
|||||||
compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include"
|
compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include"
|
||||||
|
|
||||||
compiler.c.cmd=xtensa-lx106-elf-gcc
|
compiler.c.cmd=xtensa-lx106-elf-gcc
|
||||||
compiler.c.flags=-c -Os -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -MMD -std=c99
|
compiler.c.flags=-c -Os -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=c99
|
||||||
|
|
||||||
compiler.S.cmd=xtensa-lx106-elf-gcc
|
compiler.S.cmd=xtensa-lx106-elf-gcc
|
||||||
compiler.S.flags=-c -g -x assembler-with-cpp -MMD
|
compiler.S.flags=-c -g -x assembler-with-cpp -MMD
|
||||||
@ -25,7 +25,7 @@ compiler.c.elf.cmd=xtensa-lx106-elf-gcc
|
|||||||
compiler.c.elf.libs=-lm -lgcc -lhal -lphy -lnet80211 -llwip -lwpa -lmain -lpp -lsmartconfig
|
compiler.c.elf.libs=-lm -lgcc -lhal -lphy -lnet80211 -llwip -lwpa -lmain -lpp -lsmartconfig
|
||||||
|
|
||||||
compiler.cpp.cmd=xtensa-lx106-elf-g++
|
compiler.cpp.cmd=xtensa-lx106-elf-g++
|
||||||
compiler.cpp.flags=-c -Os -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -std=c++11 -MMD
|
compiler.cpp.flags=-c -Os -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD
|
||||||
|
|
||||||
compiler.as.cmd=xtensa-lx106-elf-as
|
compiler.as.cmd=xtensa-lx106-elf-as
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user