Arduino FatFS
Loading...
Searching...
No Matches
fatfs.h
1/*
2
3 SD - a slightly more friendly wrapper for FatFs
4
5 This library aims to expose a subset of SD card functionality
6 in the form of a higher level "wrapper" object.
7
8 It uses the same API like the Arduino SD libaray.
9
10 License: GNU General Public License V3
11 (Because sdfatlib is licensed with this.)
12
13 (C) Copyright 2022 Phil Schatzmann
14
15*/
16
35#pragma once
36
37#ifdef ARDUINO
38#include <Stream.h>
39#else
40#include "stream/Stream.h"
41#endif
42
43#include "fatfs-drivers.h"
44#include "ff/ff.h"
45
46#define FILE_READ FA_READ
47#define FILE_WRITE (FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_APPEND)
48
49namespace fatfs {
50using namespace fatfs;
51
52// forward declaration
53class SDClass;
54
60class File : public Stream {
61 friend class SDClass;
62
63 public:
64 File() = default;
65 File(FatFs *fs) { this->fs = fs; }
66 ~File() {
67 if (is_open) close();
68 }
69
70 virtual size_t write(uint8_t ch) override {
71 if (fs == nullptr) return 0;
72 int rc = fs->f_putc(ch, &file);
73 return rc == EOF ? 0 : 1;
74 }
75
76 virtual size_t write(const uint8_t *buf, size_t size) override {
77 if (fs == nullptr) return 0;
78 UINT result;
79 FRESULT rc = fs->f_write(&file, buf, size, &result);
80 return rc == FR_OK ? result : 0;
81 }
82
84 virtual int read() override {
85 UINT result;
86 char buf[1] = {0};
87 readBytes((uint8_t *)buf, 1);
88 return result == 1 ? buf[0] : -1;
89 }
90
92 int peek() override {
93 uint32_t pos = position();
94 int result = read();
95 seek(pos);
96 return result;
97 }
98
99 int available() override { return info.fsize - position(); }
100
101 int availableForWrite() override { return get_free_space(); }
102
103 void flush() override {
104 if (!isDirectory()) fs->f_sync(&file);
105 }
106
107 virtual size_t readBytes(uint8_t *data, size_t len) {
108 if (isDirectory()) return 0;
109 UINT result;
110 auto rc = fs->f_read(&file, data, len, &result);
111 return rc == FR_OK ? result : 0;
112 }
113
114 int read(void *buf, size_t nbyte) { return readBytes((uint8_t *)buf, nbyte); }
115
116 bool seek(uint32_t pos) {
117 if (isDirectory()) return 0;
118 return fs->f_lseek(&file, pos);
119 }
120
121 uint32_t position() {
122 if (isDirectory()) return 0;
123 return fs->f_tell(&file);
124 }
125
126 uint32_t size() { return fs->f_size(&file); }
127
128 void close() {
129 if (isDirectory())
130 fs->f_closedir(&dir);
131 else
132 fs->f_close(&file);
133
134 memset(&dir,0,sizeof(dir));
135 memset(&file,0,sizeof(file));
136 memset(&info, 0, sizeof(info));
137 is_open = false;
138 }
139
140 char *name() { return info.fname; }
141
143 void getName(char *name, int len) { strncpy(name, info.fname, len); }
144
145 bool isDirectory(void) { return info.fattrib & AM_DIR; }
146
147 File openNextFile(uint8_t mode = FA_READ) {
148 File result;
149 FRESULT rc = fs->f_findnext(&dir, &result.info);
150 if (rc == FR_OK) {
151 result.is_open = true;
152 if (!result.isDirectory()) {
153 fs->f_open(&result.file, result.name(), mode);
154 } else {
155 fs->f_opendir(&result.dir, result.name());
156 }
157 }
158 return result;
159 }
160 void rewindDirectory(void) { fs->f_rewinddir(&dir); }
161
162 operator bool() { return is_open && error() == 0; }
163
164 bool isEOF() {
165 if (isDirectory()) return false;
166 return fs->f_eof(&file);
167 }
168
169 uint8_t error() { return fs->f_error(&file); }
170
171 using Print::print;
172 using Print::println;
173 using Print::write;
174
176 FIL *getFIL() { return isDirectory() ? nullptr : &file; }
178 DIR *getDIR() { return isDirectory() ? &dir : nullptr; }
180 FatFs *getFatFs() { return fs; }
182 IO *getDriver() { return fs->getDriver(); }
183
184 protected:
185 FIL file = {0};
186 DIR dir = {0};
187 FILINFO info = {0};
188 FatFs *fs = nullptr;
189 bool is_open = false;
190
192 bool update_stat(FatFs &fat_fs, const char *filepath) {
193 is_open = fs->f_stat(filepath, &info) == FR_OK;
194 return is_open;
195 }
196
197 size_t get_free_space() {
198#if FF_FS_MINIMIZE == 0
199 DWORD fre_clust, fre_sect;
200 FATFS *fatfs;
201
202 // Get volume information and free clusters of default drive
203 auto res = fs->f_getfree("", &fre_clust, &fatfs);
204 if (res) return 0;
205
206#if FF_MAX_SS != FF_MIN_SS
207 size_t sector_size = fil.ssize; /* Sector size (512, 1024, 2048 or 4096) */
208#else
209 size_t sector_size = FF_MAX_SS;
210#endif
211
212 // free sectors * sector size
213 return (fre_clust * fatfs->csize) * sector_size;
214#else
215 return Stream::avaiableForWrite();
216#endif
217 }
218};
219
225class SDClass {
226 public:
227 SDClass() {
228#ifdef ARDUINO
229 setDriver(drv);
230#endif
231 };
232 SDClass(IO &driver) { setDriver(driver); }
233 ~SDClass() { end(); }
234
236 bool begin(IO &driver) {
237 setDriver(driver);
238 return begin();
239 }
240
243 bool begin() {
244 if (getDriver() == nullptr) return false;
245 return handleError(getDriver()->mount(fat_fs));
246 }
247
248#ifdef ARDUINO
250 bool begin(int cs, SPIClass &spi = SPI) {
251 drv.setSPI(cs, spi);
252 return begin();
253 }
254#endif
257 void end() {
258 if (getDriver() != nullptr) getDriver()->un_mount(fat_fs);
259 delete[] (work_buffer);
260 work_buffer = nullptr;
261 }
262
266 File open(const char *filename, uint8_t mode = FILE_READ) {
267 File file{&fat_fs};
268 if (mode & FA_WRITE || file.update_stat(fat_fs, filename)) {
269 FRESULT result;
270 if (file.isDirectory()) {
271 result = fat_fs.f_opendir(&file.dir, filename);
272 } else {
273 result = fat_fs.f_open(&file.file, filename, mode);
274 }
275 file.is_open = handleError(result);
276 }
277 return file;
278 }
279
280 File open(const String &filename, uint8_t mode = FILE_READ) {
281 return open(filename.c_str(), mode);
282 }
283
285 bool exists(const char *filepath) {
286 FILINFO info;
287 FRESULT rc = fat_fs.f_stat(filepath, &info); /* Get file status */
288 return rc == FR_OK;
289 }
290
291 bool exists(const String &filepath) { return exists(filepath.c_str()); }
292
295 bool mkdir(const char *filepath) { return fat_fs.f_mkdir(filepath) == FR_OK; }
296 bool mkdir(const String &filepath) { return mkdir(filepath.c_str()); }
297
299 bool remove(const char *filepath) {
300 return fat_fs.f_unlink(filepath) == FR_OK;
301 }
302 bool remove(const String &filepath) { return remove(filepath.c_str()); }
303
304 bool rmdir(const char *filepath) {
305 return fat_fs.f_unlink(filepath) == FR_OK;
306 }
307 bool rmdir(const String &filepath) { return rmdir(filepath.c_str()); }
308
309#if FF_ARDUINO_LEVEL == 1
311 bool chdir(const char *filepath) { return fat_fs.f_chdir(filepath) == FR_OK; }
313 bool chdir(String filepath) { return chdir(filepath.c_str()); }
316 bool getcwd(char *buff, size_t len) {
317 return fat_fs.f_getcwd(buff, len) == FR_OK;
318 }
319
320#if FF_USE_MKFS == 1
322 bool mkfs(int workBufferSize = FF_MAX_SS) {
323 if (work_buffer == nullptr) work_buffer = new uint8_t[workBufferSize];
324 return handleError(fat_fs.f_mkfs("", nullptr, work_buffer, workBufferSize));
325 }
326#endif
327
328#if FF_FS_MINIMIZE == 0
330 size_t free() { return File(&fat_fs).availableForWrite(); }
331#endif
332
334 FatFs *getFatFs() { return &fat_fs; }
335
337 void setDriver(IO &driver) { fat_fs.setDriver(driver); }
338
340 IO *getDriver() { return fat_fs.getDriver(); }
341
342#endif
343
344 protected:
345#ifdef ARDUINO
347#endif
348 FatFs fat_fs;
349 uint8_t *work_buffer = nullptr;
350
351 bool handleError(FRESULT rc) {
352 if (rc != FR_OK) {
353 Serial.print("fatfs: error no: ");
354 Serial.println((int)rc);
355 return false;
356 }
357 return true;
358 }
359
360#if FF_ARDUINO_LEVEL == 0
362 void setDriver(IO &driver) { fat_fs.setDriver(driver); }
364 IO *getDriver() { return fat_fs.getDriver(); }
365
366#endif
367
368
369};
370
371} // namespace fatfs
372
373// This ensure compatibility with sketches that uses only SD library
374#if FF_NAMESPACE
375using namespace fatfs;
376#endif
377
378static fatfs::SDClass SD;
Accessing a SD card via the Arduino SPI API.
Definition ArduinoSpiIO.h:41
API for FatFS See http://elm-chan.org/fsw/ff/00index_e.html.
Definition ff.h:34
FRESULT f_close(FIL *fp)
Definition ff-inc.h:4071
FRESULT f_getcwd(TCHAR *buff, UINT len)
FRESULT f_findnext(DIR *dp, FILINFO *fno)
FRESULT f_stat(const TCHAR *path, FILINFO *fno)
Definition ff-inc.h:4631
FRESULT f_opendir(DIR *dp, const TCHAR *path)
Definition ff-inc.h:4449
FRESULT f_unlink(const TCHAR *path)
Definition ff-inc.h:4806
FRESULT f_getfree(const TCHAR *path, DWORD *nclst, FATFS **fatfs)
Definition ff-inc.h:4666
FRESULT f_sync(FIL *fp)
Definition ff-inc.h:3990
FRESULT f_mkfs(const TCHAR *path, const MKFS_PARM *opt, void *work, UINT len)
Definition ff-inc.h:5714
FRESULT f_lseek(FIL *fp, FSIZE_t ofs)
Definition ff-inc.h:4286
FRESULT f_write(FIL *fp, const void *buff, UINT btw, UINT *bw)
Definition ff-inc.h:3868
FRESULT f_read(FIL *fp, void *buff, UINT btr, UINT *br)
Definition ff-inc.h:3767
FRESULT f_chdir(const TCHAR *path)
FRESULT f_mkdir(const TCHAR *path)
Definition ff-inc.h:4900
FRESULT f_closedir(DIR *dp)
Definition ff-inc.h:4515
int f_putc(TCHAR c, FIL *fp)
Definition ff-inc.h:6536
FRESULT f_open(FIL *fp, const TCHAR *path, BYTE mode)
Definition ff-inc.h:3575
IO * getDriver()
Definition ff.h:40
File implementation for fatfs.
Definition fatfs.h:60
int peek() override
Rather inefficient: to be avoided.
Definition fatfs.h:92
void getName(char *name, int len)
Provides the name: getName() is supported by the SDFat Library.
Definition fatfs.h:143
FatFs * getFatFs()
Access to low level FatFS api to use functionality not exposed by this API.
Definition fatfs.h:180
FIL * getFIL()
Access to low level FatFS api.
Definition fatfs.h:176
DIR * getDIR()
Access to low level FatFS api.
Definition fatfs.h:178
bool update_stat(FatFs &fat_fs, const char *filepath)
update fs, info and is_open
Definition fatfs.h:192
IO * getDriver()
Access lo low level driver.
Definition fatfs.h:182
virtual int read() override
Rather inefficient: to be avoided.
Definition fatfs.h:84
FatFS interface definition.
Definition IO.h:74
virtual FRESULT un_mount(FatFs &fs)
unmount the file system - implementation at end of header to avoid recursive include
Definition IO.h:101
SDClass: starting driver, access to files.
Definition fatfs.h:225
bool chdir(const char *filepath)
Change directoy: extended functionality not available in Arduino SD API.
Definition fatfs.h:311
void setDriver(IO &driver)
Set the driver.
Definition fatfs.h:337
void end()
Definition fatfs.h:257
bool mkdir(const char *filepath)
Definition fatfs.h:295
bool chdir(String filepath)
Change directoy: extended functionality not available in Arduino SD API.
Definition fatfs.h:313
bool begin(IO &driver)
Initialization of SD card: Use before other methods.
Definition fatfs.h:236
FatFs * getFatFs()
Access to low level FatFS api to use functionality not exposed by this API.
Definition fatfs.h:334
bool mkfs(int workBufferSize=FF_MAX_SS)
format drive
Definition fatfs.h:322
File open(const char *filename, uint8_t mode=FILE_READ)
Definition fatfs.h:266
bool getcwd(char *buff, size_t len)
Definition fatfs.h:316
bool exists(const char *filepath)
Methods to determine if the requested file path exists.
Definition fatfs.h:285
size_t free()
get free space in bytes
Definition fatfs.h:330
bool begin(int cs, SPIClass &spi=SPI)
Compatibility with SD library: we use the Arduino SPI SD driver.
Definition fatfs.h:250
IO * getDriver()
Access lo low level driver.
Definition fatfs.h:340
bool begin()
Initialization of SD card. We use the SPI SD driver if nothing has been defined in the constructor.
Definition fatfs.h:243
bool remove(const char *filepath)
Delete the file.
Definition fatfs.h:299
Definition ffdef.h:200
Definition ffdef.h:98
Definition ffdef.h:218
Definition ffdef.h:175