Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LittleFileSystem.cpp Source File

LittleFileSystem.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2017 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "filesystem/mbed_filesystem.h"
00017 #include "LittleFileSystem.h"
00018 #include "errno.h"
00019 #include "lfs.h"
00020 #include "lfs_util.h"
00021 #include "MbedCRC.h"
00022 
00023 using namespace mbed;
00024 
00025 extern "C" void lfs_crc(uint32_t *crc, const void *buffer, size_t size)
00026 {
00027     uint32_t initial_xor = *crc;    
00028     MbedCRC<POLY_32BIT_REV_ANSI, 32> ct(initial_xor, 0x0, true, false);
00029     ct.compute((void *)buffer, size, (uint32_t *) crc);
00030 }
00031 
00032 ////// Conversion functions //////
00033 static int lfs_toerror(int err)
00034 {
00035     switch (err) {
00036         case LFS_ERR_OK:        return 0;
00037         case LFS_ERR_IO:        return -EIO;
00038         case LFS_ERR_NOENT:     return -ENOENT;
00039         case LFS_ERR_EXIST:     return -EEXIST;
00040         case LFS_ERR_NOTDIR:    return -ENOTDIR;
00041         case LFS_ERR_ISDIR:     return -EISDIR;
00042         case LFS_ERR_INVAL:     return -EINVAL;
00043         case LFS_ERR_NOSPC:     return -ENOSPC;
00044         case LFS_ERR_NOMEM:     return -ENOMEM;
00045         case LFS_ERR_CORRUPT:   return -EILSEQ;
00046         default:                return err;
00047     }
00048 }
00049 
00050 static int lfs_fromflags(int flags)
00051 {
00052     return (
00053         (((flags & 3) == O_RDONLY) ? LFS_O_RDONLY : 0) |
00054         (((flags & 3) == O_WRONLY) ? LFS_O_WRONLY : 0) |
00055         (((flags & 3) == O_RDWR)   ? LFS_O_RDWR   : 0) |
00056         ((flags & O_CREAT)  ? LFS_O_CREAT  : 0) |
00057         ((flags & O_EXCL)   ? LFS_O_EXCL   : 0) |
00058         ((flags & O_TRUNC)  ? LFS_O_TRUNC  : 0) |
00059         ((flags & O_APPEND) ? LFS_O_APPEND : 0));
00060 }
00061 
00062 static int lfs_fromwhence(int whence)
00063 {
00064     switch (whence) {
00065         case SEEK_SET: return LFS_SEEK_SET;
00066         case SEEK_CUR: return LFS_SEEK_CUR;
00067         case SEEK_END: return LFS_SEEK_END;
00068         default: return whence;
00069     }
00070 }
00071 
00072 static int lfs_tomode(int type)
00073 {
00074     int mode = S_IRWXU | S_IRWXG | S_IRWXO;
00075     switch (type) {
00076         case LFS_TYPE_DIR: return mode | S_IFDIR;
00077         case LFS_TYPE_REG: return mode | S_IFREG;
00078         default: return 0;
00079     }
00080 }
00081 
00082 static int lfs_totype(int type)
00083 {
00084     switch (type) {
00085         case LFS_TYPE_DIR: return DT_DIR;
00086         case LFS_TYPE_REG: return DT_REG;
00087         default: return DT_UNKNOWN;
00088     }
00089 }
00090 
00091 
00092 ////// Block device operations //////
00093 static int lfs_bd_read(const struct lfs_config *c, lfs_block_t block,
00094         lfs_off_t off, void *buffer, lfs_size_t size) {
00095     BlockDevice *bd = (BlockDevice *)c->context;
00096     return bd->read(buffer, (bd_addr_t)block*c->block_size + off, size);
00097 }
00098 
00099 static int lfs_bd_prog(const struct lfs_config *c, lfs_block_t block,
00100         lfs_off_t off, const void *buffer, lfs_size_t size) {
00101     BlockDevice *bd = (BlockDevice *)c->context;
00102     return bd->program(buffer, (bd_addr_t)block*c->block_size + off, size);
00103 }
00104 
00105 static int lfs_bd_erase(const struct lfs_config *c, lfs_block_t block)
00106 {
00107     BlockDevice *bd = (BlockDevice *)c->context;
00108     return bd->erase((bd_addr_t)block*c->block_size, c->block_size);
00109 }
00110 
00111 static int lfs_bd_sync(const struct lfs_config *c)
00112 {
00113     BlockDevice *bd = (BlockDevice *)c->context;
00114     return bd->sync();
00115 }
00116 
00117 
00118 ////// Generic filesystem operations //////
00119 
00120 // Filesystem implementation (See LittleFileSystem.h)
00121 LittleFileSystem::LittleFileSystem(const char *name, BlockDevice *bd,
00122         lfs_size_t read_size, lfs_size_t prog_size,
00123         lfs_size_t block_size, lfs_size_t lookahead)
00124         : FileSystem(name)
00125         , _read_size(read_size)
00126         , _prog_size(prog_size)
00127         , _block_size(block_size)
00128         , _lookahead(lookahead) {
00129     if (bd) {
00130         mount(bd);
00131     }
00132 }
00133 
00134 LittleFileSystem::~LittleFileSystem() {
00135     // nop if unmounted
00136     unmount();
00137 }
00138 
00139 int LittleFileSystem::mount(BlockDevice *bd)
00140 {
00141     _mutex.lock();
00142     LFS_INFO("mount(%p)", bd);
00143     _bd = bd;
00144     int err = _bd->init();
00145     if (err) {
00146         _bd = NULL;
00147         LFS_INFO("mount -> %d", err);
00148         _mutex.unlock();
00149         return err;
00150     }
00151 
00152     memset(&_config, 0, sizeof(_config));
00153     _config.context = bd;
00154     _config.read  = lfs_bd_read;
00155     _config.prog  = lfs_bd_prog;
00156     _config.erase = lfs_bd_erase;
00157     _config.sync  = lfs_bd_sync;
00158     _config.read_size   = bd->get_read_size();
00159     if (_config.read_size < _read_size) {
00160         _config.read_size = _read_size;
00161     }
00162     _config.prog_size   = bd->get_program_size();
00163     if (_config.prog_size < _prog_size) {
00164         _config.prog_size = _prog_size;
00165     }
00166     _config.block_size  = bd->get_erase_size();
00167     if (_config.block_size < _block_size) {
00168         _config.block_size = _block_size;
00169     }
00170     _config.block_count = bd->size() / _config.block_size;
00171     _config.lookahead = 32 * ((_config.block_count+31)/32);
00172     if (_config.lookahead > _lookahead) {
00173         _config.lookahead = _lookahead;
00174     }
00175 
00176     err = lfs_mount(&_lfs, &_config);
00177     if (err) {
00178         _bd = NULL;
00179         LFS_INFO("mount -> %d", lfs_toerror(err));
00180         _mutex.unlock();
00181         return lfs_toerror(err);
00182     }
00183 
00184     _mutex.unlock();
00185     LFS_INFO("mount -> %d", 0);
00186     return 0;
00187 }
00188 
00189 int LittleFileSystem::unmount()
00190 {
00191     _mutex.lock();
00192     LFS_INFO("unmount(%s)", "");
00193     int res = 0;
00194     if (_bd) {
00195         int err = lfs_unmount(&_lfs);
00196         if (err && !res) {
00197             res = lfs_toerror(err);
00198         }
00199 
00200         err = _bd->deinit();
00201         if (err && !res) {
00202             res = err;
00203         }
00204 
00205         _bd = NULL;
00206     }
00207     
00208     LFS_INFO("unmount -> %d", res);
00209     _mutex.unlock();
00210     return res;
00211 }
00212 
00213 int LittleFileSystem::format(BlockDevice *bd,
00214         lfs_size_t read_size, lfs_size_t prog_size,
00215         lfs_size_t block_size, lfs_size_t lookahead) {
00216     LFS_INFO("format(%p, %ld, %ld, %ld, %ld)",
00217             bd, read_size, prog_size, block_size, lookahead);
00218     int err = bd->init();
00219     if (err) {
00220         LFS_INFO("format -> %d", err);
00221         return err;
00222     }
00223 
00224     lfs_t _lfs;
00225     struct lfs_config _config;
00226     
00227     memset(&_config, 0, sizeof(_config));
00228     _config.context = bd;
00229     _config.read  = lfs_bd_read;
00230     _config.prog  = lfs_bd_prog;
00231     _config.erase = lfs_bd_erase;
00232     _config.sync  = lfs_bd_sync;
00233     _config.read_size   = bd->get_read_size();
00234     if (_config.read_size < read_size) {
00235         _config.read_size = read_size;
00236     }
00237     _config.prog_size   = bd->get_program_size();
00238     if (_config.prog_size < prog_size) {
00239         _config.prog_size = prog_size;
00240     }
00241     _config.block_size  = bd->get_erase_size();
00242     if (_config.block_size < block_size) {
00243         _config.block_size = block_size;
00244     }
00245     _config.block_count = bd->size() / _config.block_size;
00246     _config.lookahead = 32 * ((_config.block_count+31)/32);
00247     if (_config.lookahead > lookahead) {
00248         _config.lookahead = lookahead;
00249     }
00250 
00251     err = lfs_format(&_lfs, &_config);
00252     if (err) {
00253         LFS_INFO("format -> %d", lfs_toerror(err));
00254         return lfs_toerror(err);
00255     }
00256 
00257     err = bd->deinit();
00258     if (err) {
00259         LFS_INFO("format -> %d", err);
00260         return err;
00261     }
00262 
00263     LFS_INFO("format -> %d", 0);
00264     return 0;
00265 }
00266 
00267 int LittleFileSystem::reformat(BlockDevice *bd)
00268 {
00269     _mutex.lock();
00270     LFS_INFO("reformat(%p)", bd);
00271     if (_bd) {
00272         if (!bd) {
00273             bd = _bd;
00274         }
00275 
00276         int err = unmount();
00277         if (err) {
00278             LFS_INFO("reformat -> %d", err);
00279             _mutex.unlock();
00280             return err;
00281         }
00282     }
00283 
00284     if (!bd) {
00285         LFS_INFO("reformat -> %d", -ENODEV);
00286         _mutex.unlock();
00287         return -ENODEV;
00288     }
00289 
00290     int err = LittleFileSystem::format(bd,
00291             _read_size, _prog_size, _block_size, _lookahead);
00292     if (err) {
00293         LFS_INFO("reformat -> %d", err);
00294         _mutex.unlock();
00295         return err;
00296     }
00297 
00298     err = mount(bd);
00299     if (err) {
00300         LFS_INFO("reformat -> %d", err);
00301         _mutex.unlock();
00302         return err;
00303     }
00304 
00305     LFS_INFO("reformat -> %d", 0);
00306     _mutex.unlock();
00307     return 0;
00308 }
00309 
00310 int LittleFileSystem::remove(const char *filename)
00311 {
00312     _mutex.lock();
00313     LFS_INFO("remove(\"%s\")", filename);
00314     int err = lfs_remove(&_lfs, filename);
00315     LFS_INFO("remove -> %d", lfs_toerror(err));
00316     _mutex.unlock();
00317     return lfs_toerror(err);
00318 }
00319 
00320 int LittleFileSystem::rename(const char *oldname, const char *newname)
00321 {
00322     _mutex.lock();
00323     LFS_INFO("rename(\"%s\", \"%s\")", oldname, newname);
00324     int err = lfs_rename(&_lfs, oldname, newname);
00325     LFS_INFO("rename -> %d", lfs_toerror(err));
00326     _mutex.unlock();
00327     return lfs_toerror(err);
00328 }
00329 
00330 int LittleFileSystem::mkdir(const char *name, mode_t mode)
00331 {
00332     _mutex.lock();
00333     LFS_INFO("mkdir(\"%s\", 0x%lx)", name, mode);
00334     int err = lfs_mkdir(&_lfs, name);
00335     LFS_INFO("mkdir -> %d", lfs_toerror(err));
00336     _mutex.unlock();
00337     return lfs_toerror(err);
00338 }
00339 
00340 int LittleFileSystem::stat(const char *name, struct stat *st)
00341 {
00342     struct lfs_info info;
00343     _mutex.lock();
00344     LFS_INFO("stat(\"%s\", %p)", name, st);
00345     int err = lfs_stat(&_lfs, name, &info);
00346     LFS_INFO("stat -> %d", lfs_toerror(err));
00347     _mutex.unlock();
00348     st->st_size = info.size;
00349     st->st_mode = lfs_tomode(info.type);
00350     return lfs_toerror(err);
00351 }
00352 
00353 static int lfs_statvfs_count(void *p, lfs_block_t b)
00354 {
00355     *(lfs_size_t *)p += 1;
00356     return 0;
00357 }
00358 
00359 int LittleFileSystem::statvfs(const char *name, struct statvfs *st)
00360 {
00361     memset(st, 0, sizeof(struct statvfs));
00362 
00363     lfs_size_t in_use = 0;
00364     _mutex.lock();
00365     LFS_INFO("statvfs(\"%s\", %p)", name, st);
00366     int err = lfs_traverse(&_lfs, lfs_statvfs_count, &in_use);
00367     LFS_INFO("statvfs -> %d", lfs_toerror(err));
00368     _mutex.unlock();
00369     if (err) {
00370         return err;
00371     }
00372 
00373     st->f_bsize  = _config.block_size;
00374     st->f_frsize = _config.block_size;
00375     st->f_blocks = _config.block_count;
00376     st->f_bfree  = _config.block_count - in_use;
00377     st->f_bavail = _config.block_count - in_use;
00378     st->f_namemax = LFS_NAME_MAX;
00379     return 0;
00380 }
00381 
00382 ////// File operations //////
00383 int LittleFileSystem::file_open(fs_file_t *file, const char *path, int flags)
00384 {
00385     lfs_file_t *f = new lfs_file_t;
00386     _mutex.lock();
00387     LFS_INFO("file_open(%p, \"%s\", 0x%x)", *file, path, flags);
00388     int err = lfs_file_open(&_lfs, f, path, lfs_fromflags(flags));
00389     LFS_INFO("file_open -> %d", lfs_toerror(err));
00390     _mutex.unlock();
00391     if (!err) {
00392         *file = f;
00393     } else {
00394         delete f;
00395     }
00396     return lfs_toerror(err);
00397 }
00398 
00399 int LittleFileSystem::file_close(fs_file_t file)
00400 {
00401     lfs_file_t *f = (lfs_file_t *)file;
00402     _mutex.lock();
00403     LFS_INFO("file_close(%p)", file);
00404     int err = lfs_file_close(&_lfs, f);
00405     LFS_INFO("file_close -> %d", lfs_toerror(err));
00406     _mutex.unlock();
00407     delete f;
00408     return lfs_toerror(err);
00409 }
00410 
00411 ssize_t LittleFileSystem::file_read(fs_file_t file, void *buffer, size_t len)
00412 {
00413     lfs_file_t *f = (lfs_file_t *)file;
00414     _mutex.lock();
00415     LFS_INFO("file_read(%p, %p, %d)", file, buffer, len);
00416     lfs_ssize_t res = lfs_file_read(&_lfs, f, buffer, len);
00417     LFS_INFO("file_read -> %d", lfs_toerror(res));
00418     _mutex.unlock();
00419     return lfs_toerror(res);
00420 }
00421 
00422 ssize_t LittleFileSystem::file_write(fs_file_t file, const void *buffer, size_t len)
00423 {
00424     lfs_file_t *f = (lfs_file_t *)file;
00425     _mutex.lock();
00426     LFS_INFO("file_write(%p, %p, %d)", file, buffer, len);
00427     lfs_ssize_t res = lfs_file_write(&_lfs, f, buffer, len);
00428     LFS_INFO("file_write -> %d", lfs_toerror(res));
00429     _mutex.unlock();
00430     return lfs_toerror(res);
00431 }
00432 
00433 int LittleFileSystem::file_sync(fs_file_t file)
00434 {
00435     lfs_file_t *f = (lfs_file_t *)file;
00436     _mutex.lock();
00437     LFS_INFO("file_sync(%p)", file);
00438     int err = lfs_file_sync(&_lfs, f);
00439     LFS_INFO("file_sync -> %d", lfs_toerror(err));
00440     _mutex.unlock();
00441     return lfs_toerror(err);
00442 }
00443 
00444 off_t LittleFileSystem::file_seek(fs_file_t file, off_t offset, int whence)
00445 {
00446     lfs_file_t *f = (lfs_file_t *)file;
00447     _mutex.lock();
00448     LFS_INFO("file_seek(%p, %ld, %d)", file, offset, whence);
00449     off_t res = lfs_file_seek(&_lfs, f, offset, lfs_fromwhence(whence));
00450     LFS_INFO("file_seek -> %d", lfs_toerror(res));
00451     _mutex.unlock();
00452     return lfs_toerror(res);
00453 }
00454 
00455 off_t LittleFileSystem::file_tell(fs_file_t file)
00456 {
00457     lfs_file_t *f = (lfs_file_t *)file;
00458     _mutex.lock();
00459     LFS_INFO("file_tell(%p)", file);
00460     off_t res = lfs_file_tell(&_lfs, f);
00461     LFS_INFO("file_tell -> %d", lfs_toerror(res));
00462     _mutex.unlock();
00463     return lfs_toerror(res);
00464 }
00465 
00466 off_t LittleFileSystem::file_size(fs_file_t file)
00467 {
00468     lfs_file_t *f = (lfs_file_t *)file;
00469     _mutex.lock();
00470     LFS_INFO("file_size(%p)", file);
00471     off_t res = lfs_file_size(&_lfs, f);
00472     LFS_INFO("file_size -> %d", lfs_toerror(res));
00473     _mutex.unlock();
00474     return lfs_toerror(res);
00475 }
00476 
00477 
00478 ////// Dir operations //////
00479 int LittleFileSystem::dir_open(fs_dir_t *dir, const char *path)
00480 {
00481     lfs_dir_t *d = new lfs_dir_t;
00482     _mutex.lock();
00483     LFS_INFO("dir_open(%p, \"%s\")", *dir, path);
00484     int err = lfs_dir_open(&_lfs, d, path);
00485     LFS_INFO("dir_open -> %d", lfs_toerror(err));
00486     _mutex.unlock();
00487     if (!err) {
00488         *dir = d;
00489     } else {
00490         delete d;
00491     }
00492     return lfs_toerror(err);
00493 }
00494 
00495 int LittleFileSystem::dir_close(fs_dir_t dir)
00496 {
00497     lfs_dir_t *d = (lfs_dir_t *)dir;
00498     _mutex.lock();
00499     LFS_INFO("dir_close(%p)", dir);
00500     int err = lfs_dir_close(&_lfs, d);
00501     LFS_INFO("dir_close -> %d", lfs_toerror(err));
00502     _mutex.unlock();
00503     delete d;
00504     return lfs_toerror(err);
00505 }
00506 
00507 ssize_t LittleFileSystem::dir_read(fs_dir_t dir, struct dirent *ent)
00508 {
00509     lfs_dir_t *d = (lfs_dir_t *)dir;
00510     struct lfs_info info;
00511     _mutex.lock();
00512     LFS_INFO("dir_read(%p, %p)", dir, ent);
00513     int res = lfs_dir_read(&_lfs, d, &info);
00514     LFS_INFO("dir_read -> %d", lfs_toerror(res));
00515     _mutex.unlock();
00516     if (res == 1) {
00517         ent->d_type = lfs_totype(info.type);
00518         strcpy(ent->d_name, info.name);
00519     }
00520     return lfs_toerror(res);
00521 }
00522 
00523 void LittleFileSystem::dir_seek(fs_dir_t dir, off_t offset)
00524 {
00525     lfs_dir_t *d = (lfs_dir_t *)dir;
00526     _mutex.lock();
00527     LFS_INFO("dir_seek(%p, %ld)", dir, offset);
00528     lfs_dir_seek(&_lfs, d, offset);
00529     LFS_INFO("dir_seek -> %s", "void");
00530     _mutex.unlock();
00531 }
00532 
00533 off_t LittleFileSystem::dir_tell(fs_dir_t dir)
00534 {
00535     lfs_dir_t *d = (lfs_dir_t *)dir;
00536     _mutex.lock();
00537     LFS_INFO("dir_tell(%p)", dir);
00538     lfs_soff_t res = lfs_dir_tell(&_lfs, d);
00539     LFS_INFO("dir_tell -> %d", lfs_toerror(res));
00540     _mutex.unlock();
00541     return lfs_toerror(res);
00542 }
00543 
00544 void LittleFileSystem::dir_rewind(fs_dir_t dir)
00545 {
00546     lfs_dir_t *d = (lfs_dir_t *)dir;
00547     _mutex.lock();
00548     LFS_INFO("dir_rewind(%p)", dir);
00549     lfs_dir_rewind(&_lfs, d);
00550     LFS_INFO("dir_rewind -> %s", "void");
00551     _mutex.unlock();
00552 }
00553