Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7206b2f

Browse filesBrowse files
lbernstoneme-no-dev
authored andcommitted
FAT on SPI Flash Library (espressif#1809)
* First commit of FFat library * Fixed reboot loops if no fat present. Added CMakeLists * Functionalize the partition checks * Cleanup, especially in format * Dont format if mounted. More wording cleanup * 16M ffat should only be on 16M board * Fix some casting issues that trip up the compiler when building as ESP-IDF component
1 parent 3028ec4 commit 7206b2f
Copy full SHA for 7206b2f

File tree

Expand file treeCollapse file tree

8 files changed

+415
-12
lines changed
Filter options
Expand file treeCollapse file tree

8 files changed

+415
-12
lines changed

‎CMakeLists.txt

Copy file name to clipboardExpand all lines: CMakeLists.txt
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ set(LIBRARY_SRCS
4040
libraries/DNSServer/src/DNSServer.cpp
4141
libraries/EEPROM/EEPROM.cpp
4242
libraries/ESPmDNS/src/ESPmDNS.cpp
43+
libraries/FFat/src/FFat.cpp
4344
libraries/FS/src/FS.cpp
4445
libraries/FS/src/vfs_api.cpp
4546
libraries/HTTPClient/src/HTTPClient.cpp
@@ -175,6 +176,7 @@ set(COMPONENT_ADD_INCLUDEDIRS
175176
libraries/DNSServer/src
176177
libraries/ESP32/src
177178
libraries/ESPmDNS/src
179+
libraries/FFat/src
178180
libraries/FS/src
179181
libraries/HTTPClient/src
180182
libraries/NetBIOS/src

‎boards.txt

Copy file name to clipboardExpand all lines: boards.txt
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ esp32.menu.PartitionScheme.no_ota.upload.maximum_size=2097152
4646
esp32.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA)
4747
esp32.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
4848
esp32.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080
49+
esp32.menu.PartitionScheme.fatflash=16M Fat
50+
esp32.menu.PartitionScheme.fatflash.build.partitions=ffat
4951

5052
esp32.menu.FlashMode.qio=QIO
5153
esp32.menu.FlashMode.qio.build.flash_mode=dio
@@ -70,6 +72,9 @@ esp32.menu.FlashSize.4M.build.flash_size=4MB
7072
esp32.menu.FlashSize.2M=2MB (16Mb)
7173
esp32.menu.FlashSize.2M.build.flash_size=2MB
7274
esp32.menu.FlashSize.2M.build.partitions=minimal
75+
esp32.menu.FlashSize.16M=16MB (128Mb)
76+
esp32.menu.FlashSize.16M.build.flash_size=16MB
77+
esp32.menu.FlashSize.16M.build.partitions=ffat
7378

7479
esp32.menu.UploadSpeed.921600=921600
7580
esp32.menu.UploadSpeed.921600.upload.speed=921600
+181Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
#include "FS.h"
2+
#include "FFat.h"
3+
4+
// You only need to format FFat the first time you run a test
5+
#define FORMAT_FFAT true
6+
7+
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
8+
Serial.printf("Listing directory: %s\r\n", dirname);
9+
10+
File root = fs.open(dirname);
11+
if(!root){
12+
Serial.println("- failed to open directory");
13+
return;
14+
}
15+
if(!root.isDirectory()){
16+
Serial.println(" - not a directory");
17+
return;
18+
}
19+
20+
File file = root.openNextFile();
21+
while(file){
22+
if(file.isDirectory()){
23+
Serial.print(" DIR : ");
24+
Serial.println(file.name());
25+
if(levels){
26+
listDir(fs, file.name(), levels -1);
27+
}
28+
} else {
29+
Serial.print(" FILE: ");
30+
Serial.print(file.name());
31+
Serial.print("\tSIZE: ");
32+
Serial.println(file.size());
33+
}
34+
file = root.openNextFile();
35+
}
36+
}
37+
38+
void readFile(fs::FS &fs, const char * path){
39+
Serial.printf("Reading file: %s\r\n", path);
40+
41+
File file = fs.open(path);
42+
if(!file || file.isDirectory()){
43+
Serial.println("- failed to open file for reading");
44+
return;
45+
}
46+
47+
Serial.println("- read from file:");
48+
while(file.available()){
49+
Serial.write(file.read());
50+
}
51+
}
52+
53+
void writeFile(fs::FS &fs, const char * path, const char * message){
54+
Serial.printf("Writing file: %s\r\n", path);
55+
56+
File file = fs.open(path, FILE_WRITE);
57+
if(!file){
58+
Serial.println("- failed to open file for writing");
59+
return;
60+
}
61+
if(file.print(message)){
62+
Serial.println("- file written");
63+
} else {
64+
Serial.println("- frite failed");
65+
}
66+
}
67+
68+
void appendFile(fs::FS &fs, const char * path, const char * message){
69+
Serial.printf("Appending to file: %s\r\n", path);
70+
71+
File file = fs.open(path, FILE_APPEND);
72+
if(!file){
73+
Serial.println("- failed to open file for appending");
74+
return;
75+
}
76+
if(file.print(message)){
77+
Serial.println("- message appended");
78+
} else {
79+
Serial.println("- append failed");
80+
}
81+
}
82+
83+
void renameFile(fs::FS &fs, const char * path1, const char * path2){
84+
Serial.printf("Renaming file %s to %s\r\n", path1, path2);
85+
if (fs.rename(path1, path2)) {
86+
Serial.println("- file renamed");
87+
} else {
88+
Serial.println("- rename failed");
89+
}
90+
}
91+
92+
void deleteFile(fs::FS &fs, const char * path){
93+
Serial.printf("Deleting file: %s\r\n", path);
94+
if(fs.remove(path)){
95+
Serial.println("- file deleted");
96+
} else {
97+
Serial.println("- delete failed");
98+
}
99+
}
100+
101+
void testFileIO(fs::FS &fs, const char * path){
102+
Serial.printf("Testing file I/O with %s\r\n", path);
103+
104+
static uint8_t buf[512];
105+
size_t len = 0;
106+
File file = fs.open(path, FILE_WRITE);
107+
if(!file){
108+
Serial.println("- failed to open file for writing");
109+
return;
110+
}
111+
112+
size_t i;
113+
Serial.print("- writing" );
114+
uint32_t start = millis();
115+
for(i=0; i<2048; i++){
116+
if ((i & 0x001F) == 0x001F){
117+
Serial.print(".");
118+
}
119+
file.write(buf, 512);
120+
}
121+
Serial.println("");
122+
uint32_t end = millis() - start;
123+
Serial.printf(" - %u bytes written in %u ms\r\n", 2048 * 512, end);
124+
file.close();
125+
126+
file = fs.open(path);
127+
start = millis();
128+
end = start;
129+
i = 0;
130+
if(file && !file.isDirectory()){
131+
len = file.size();
132+
size_t flen = len;
133+
start = millis();
134+
Serial.print("- reading" );
135+
while(len){
136+
size_t toRead = len;
137+
if(toRead > 512){
138+
toRead = 512;
139+
}
140+
file.read(buf, toRead);
141+
if ((i++ & 0x001F) == 0x001F){
142+
Serial.print(".");
143+
}
144+
len -= toRead;
145+
}
146+
Serial.println("");
147+
end = millis() - start;
148+
Serial.printf("- %u bytes read in %u ms\r\n", flen, end);
149+
file.close();
150+
} else {
151+
Serial.println("- failed to open file for reading");
152+
}
153+
}
154+
155+
void setup(){
156+
Serial.begin(115200);
157+
Serial.setDebugOutput(true);
158+
if (FORMAT_FFAT) FFat.format();
159+
if(!FFat.begin()){
160+
Serial.println("FFat Mount Failed");
161+
return;
162+
}
163+
164+
Serial.printf("Total space: %10lu\n", FFat.totalBytes());
165+
Serial.printf("Free space: %10lu\n", FFat.freeBytes());
166+
listDir(FFat, "/", 0);
167+
writeFile(FFat, "/hello.txt", "Hello ");
168+
appendFile(FFat, "/hello.txt", "World!\r\n");
169+
readFile(FFat, "/hello.txt");
170+
renameFile(FFat, "/hello.txt", "/foo.txt");
171+
readFile(FFat, "/foo.txt");
172+
deleteFile(FFat, "/foo.txt");
173+
testFileIO(FFat, "/test.txt");
174+
Serial.printf("Free space: %10lu\n", FFat.freeBytes());
175+
deleteFile(FFat, "/test.txt");
176+
Serial.println( "Test complete" );
177+
}
178+
179+
void loop(){
180+
181+
}

‎libraries/FFat/library.properties

Copy file name to clipboard
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name=FFat
2+
version=1.0
3+
author=Hristo Gochkov, Ivan Grokhtkov, Larry Bernstone
4+
maintainer=Hristo Gochkov <hristo@espressif.com>
5+
sentence=ESP32 FAT on Flash File System
6+
paragraph=
7+
category=Data Storage
8+
url=
9+
architectures=esp32

‎libraries/FFat/src/FFat.cpp

Copy file name to clipboard
+144Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "vfs_api.h"
16+
extern "C" {
17+
#include "esp_vfs_fat.h"
18+
#include "diskio.h"
19+
#include "diskio_wl.h"
20+
#include "vfs_fat_internal.h"
21+
}
22+
#include "FFat.h"
23+
24+
using namespace fs;
25+
26+
F_Fat::F_Fat(FSImplPtr impl)
27+
: FS(impl)
28+
{}
29+
30+
const esp_partition_t *check_ffat_partition(const char* label)
31+
{
32+
const esp_partition_t* ck_part = esp_partition_find_first(
33+
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, label);
34+
if (!ck_part) {
35+
log_e("No FAT partition found with label %s", label);
36+
return NULL;
37+
}
38+
return ck_part;
39+
}
40+
41+
bool F_Fat::begin(bool formatOnFail, const char * basePath, uint8_t maxOpenFiles, const char * partitionLabel)
42+
{
43+
if(_wl_handle){
44+
log_w("Already Mounted!");
45+
return true;
46+
}
47+
48+
if (!check_ffat_partition(partitionLabel)) return false;
49+
50+
esp_vfs_fat_mount_config_t conf = {
51+
.format_if_mount_failed = formatOnFail,
52+
.max_files = maxOpenFiles
53+
};
54+
esp_err_t err = esp_vfs_fat_spiflash_mount(basePath, partitionLabel, &conf, &_wl_handle);
55+
if(err){
56+
log_e("Mounting FFat partition failed! Error: %d", err);
57+
return false;
58+
}
59+
_impl->mountpoint(basePath);
60+
return true;
61+
}
62+
63+
void F_Fat::end()
64+
{
65+
if(_wl_handle){
66+
esp_err_t err = esp_vfs_fat_spiflash_unmount(_impl->mountpoint(), _wl_handle);
67+
if(err){
68+
log_e("Unmounting FFat partition failed! Error: %d", err);
69+
return;
70+
}
71+
_wl_handle = NULL;
72+
_impl->mountpoint(NULL);
73+
}
74+
}
75+
76+
bool F_Fat::format(bool full_wipe, char* partitionLabel)
77+
{
78+
esp_err_t result;
79+
if(_wl_handle){
80+
log_w("Already Mounted!");
81+
return false;
82+
}
83+
wl_handle_t temp_handle;
84+
// Attempt to mount to see if there is already data
85+
const esp_partition_t *ffat_partition = check_ffat_partition(partitionLabel);
86+
if (!ffat_partition) return false;
87+
result = wl_mount(ffat_partition, &temp_handle);
88+
89+
if (result == ESP_OK) {
90+
// Wipe disk- quick just wipes the FAT. Full zeroes the whole disk
91+
uint32_t wipe_size = full_wipe ? wl_size(temp_handle) : 16384;
92+
wl_erase_range(temp_handle, 0, wipe_size);
93+
wl_unmount(temp_handle);
94+
}
95+
// Now do a mount with format_if_fail (which it will)
96+
esp_vfs_fat_mount_config_t conf = {
97+
.format_if_mount_failed = true,
98+
.max_files = 1
99+
};
100+
result = esp_vfs_fat_spiflash_mount("/format_ffat", partitionLabel, &conf, &temp_handle);
101+
esp_vfs_fat_spiflash_unmount("/format_ffat", temp_handle);
102+
return result;
103+
}
104+
105+
size_t F_Fat::totalBytes()
106+
{
107+
FATFS *fs;
108+
DWORD free_clust, tot_sect, sect_size;
109+
110+
BYTE pdrv = ff_diskio_get_pdrv_wl(_wl_handle);
111+
char drv[3] = {(char)(48+pdrv), ':', 0};
112+
FRESULT res = f_getfree(drv, &free_clust, &fs);
113+
tot_sect = (fs->n_fatent - 2) * fs->csize;
114+
sect_size = CONFIG_WL_SECTOR_SIZE;
115+
return tot_sect * sect_size;
116+
}
117+
118+
size_t F_Fat::freeBytes()
119+
{
120+
121+
FATFS *fs;
122+
DWORD free_clust, free_sect, sect_size;
123+
124+
BYTE pdrv = ff_diskio_get_pdrv_wl(_wl_handle);
125+
char drv[3] = {(char)(48+pdrv), ':', 0};
126+
FRESULT res = f_getfree(drv, &free_clust, &fs);
127+
free_sect = free_clust * fs->csize;
128+
sect_size = CONFIG_WL_SECTOR_SIZE;
129+
return free_sect * sect_size;
130+
}
131+
132+
bool F_Fat::exists(const char* path)
133+
{
134+
File f = open(path, "r");
135+
return (f == true) && !f.isDirectory();
136+
}
137+
138+
bool F_Fat::exists(const String& path)
139+
{
140+
return exists(path.c_str());
141+
}
142+
143+
144+
F_Fat FFat = F_Fat(FSImplPtr(new VFSImpl()));

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.