Filesystem library designed for flash devices

Dependents:   flash-fs-example Dragonfly_Filesystem_Example STM32F407VET6_SPIFlash Dragonfly_Filesystem_Example_mbed_5

Committer:
Leon Lindenfelser
Date:
Fri Jun 26 14:31:42 2020 -0500
Revision:
3:9adcf49bb77d
Parent:
2:de478b250060
Update to latest from Multitech git repo

1. Add timeout when waiting for WIP
2. Check 'write in progress bit' after writing the status register
3. Add ability to write the status register
4. Read identification function actually reads identification
5. Hardcode memory size as parameter in constructor
6. Move wakeup() call after CS, WP, and HOLD setup so it wakes the flash if it was sleeping

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mfiore 0:bb4e812f7c97 1 /*
mfiore 0:bb4e812f7c97 2 * spiffs_hydrogen.c
mfiore 0:bb4e812f7c97 3 *
mfiore 0:bb4e812f7c97 4 * Created on: Jun 16, 2013
mfiore 0:bb4e812f7c97 5 * Author: petera
mfiore 0:bb4e812f7c97 6 */
mfiore 0:bb4e812f7c97 7
mfiore 0:bb4e812f7c97 8 #include "spiffs.h"
mfiore 0:bb4e812f7c97 9 #include "spiffs_nucleus.h"
mfiore 0:bb4e812f7c97 10
mfiore 0:bb4e812f7c97 11 static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh);
mfiore 0:bb4e812f7c97 12
mfiore 0:bb4e812f7c97 13 #if SPIFFS_BUFFER_HELP
mfiore 0:bb4e812f7c97 14 u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs) {
mfiore 0:bb4e812f7c97 15 return num_descs * sizeof(spiffs_fd);
mfiore 0:bb4e812f7c97 16 }
mfiore 0:bb4e812f7c97 17 #if SPIFFS_CACHE
mfiore 0:bb4e812f7c97 18 u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages) {
mfiore 0:bb4e812f7c97 19 return sizeof(spiffs_cache) + num_pages * (sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs));
mfiore 0:bb4e812f7c97 20 }
mfiore 0:bb4e812f7c97 21 #endif
mfiore 0:bb4e812f7c97 22 #endif
mfiore 0:bb4e812f7c97 23
mfiore 0:bb4e812f7c97 24 s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
mfiore 0:bb4e812f7c97 25 u8_t *fd_space, u32_t fd_space_size,
Mike Fiore 2:de478b250060 26 u8_t *cache, u32_t cache_size,
mfiore 0:bb4e812f7c97 27 spiffs_check_callback check_cb_f) {
mfiore 0:bb4e812f7c97 28 SPIFFS_LOCK(fs);
mfiore 0:bb4e812f7c97 29 memset(fs, 0, sizeof(spiffs));
mfiore 0:bb4e812f7c97 30 memcpy(&fs->cfg, config, sizeof(spiffs_config));
mfiore 0:bb4e812f7c97 31 fs->block_count = SPIFFS_CFG_PHYS_SZ(fs) / SPIFFS_CFG_LOG_BLOCK_SZ(fs);
mfiore 0:bb4e812f7c97 32 fs->work = &work[0];
mfiore 0:bb4e812f7c97 33 fs->lu_work = &work[SPIFFS_CFG_LOG_PAGE_SZ(fs)];
mfiore 0:bb4e812f7c97 34 memset(fd_space, 0, fd_space_size);
mfiore 0:bb4e812f7c97 35 // align fd_space pointer to pointer size byte boundary, below is safe
mfiore 0:bb4e812f7c97 36 u8_t ptr_size = sizeof(void*);
mfiore 0:bb4e812f7c97 37 #pragma GCC diagnostic push
mfiore 0:bb4e812f7c97 38 #pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
mfiore 0:bb4e812f7c97 39 u8_t addr_lsb = ((u8_t)fd_space) & (ptr_size-1);
mfiore 0:bb4e812f7c97 40 #pragma GCC diagnostic pop
mfiore 0:bb4e812f7c97 41 if (addr_lsb) {
mfiore 0:bb4e812f7c97 42 fd_space += (ptr_size-addr_lsb);
mfiore 0:bb4e812f7c97 43 fd_space_size -= (ptr_size-addr_lsb);
mfiore 0:bb4e812f7c97 44 }
mfiore 0:bb4e812f7c97 45 fs->fd_space = fd_space;
mfiore 0:bb4e812f7c97 46 fs->fd_count = (fd_space_size/sizeof(spiffs_fd));
mfiore 0:bb4e812f7c97 47
mfiore 0:bb4e812f7c97 48 // align cache pointer to 4 byte boundary, below is safe
mfiore 0:bb4e812f7c97 49 #pragma GCC diagnostic push
mfiore 0:bb4e812f7c97 50 #pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
mfiore 0:bb4e812f7c97 51 addr_lsb = ((u8_t)cache) & (ptr_size-1);
mfiore 0:bb4e812f7c97 52 #pragma GCC diagnostic pop
mfiore 0:bb4e812f7c97 53 if (addr_lsb) {
mfiore 0:bb4e812f7c97 54 cache += (ptr_size-addr_lsb);
mfiore 0:bb4e812f7c97 55 cache_size -= (ptr_size-addr_lsb);
mfiore 0:bb4e812f7c97 56 }
mfiore 0:bb4e812f7c97 57 if (cache_size & (ptr_size-1)) {
mfiore 0:bb4e812f7c97 58 cache_size -= (cache_size & (ptr_size-1));
mfiore 0:bb4e812f7c97 59 }
mfiore 0:bb4e812f7c97 60 #if SPIFFS_CACHE
mfiore 0:bb4e812f7c97 61 fs->cache = cache;
mfiore 0:bb4e812f7c97 62 fs->cache_size = cache_size;
mfiore 0:bb4e812f7c97 63 spiffs_cache_init(fs);
mfiore 0:bb4e812f7c97 64 #endif
mfiore 0:bb4e812f7c97 65
mfiore 0:bb4e812f7c97 66 s32_t res = spiffs_obj_lu_scan(fs);
mfiore 0:bb4e812f7c97 67 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 68
mfiore 0:bb4e812f7c97 69 SPIFFS_DBG("page index byte len: %i\n", SPIFFS_CFG_LOG_PAGE_SZ(fs));
mfiore 0:bb4e812f7c97 70 SPIFFS_DBG("object lookup pages: %i\n", SPIFFS_OBJ_LOOKUP_PAGES(fs));
mfiore 0:bb4e812f7c97 71 SPIFFS_DBG("page pages per block: %i\n", SPIFFS_PAGES_PER_BLOCK(fs));
mfiore 0:bb4e812f7c97 72 SPIFFS_DBG("page header length: %i\n", sizeof(spiffs_page_header));
mfiore 0:bb4e812f7c97 73 SPIFFS_DBG("object header index entries: %i\n", SPIFFS_OBJ_HDR_IX_LEN(fs));
mfiore 0:bb4e812f7c97 74 SPIFFS_DBG("object index entries: %i\n", SPIFFS_OBJ_IX_LEN(fs));
mfiore 0:bb4e812f7c97 75 SPIFFS_DBG("available file descriptors: %i\n", fs->fd_count);
mfiore 0:bb4e812f7c97 76 SPIFFS_DBG("free blocks: %i\n", fs->free_blocks);
mfiore 0:bb4e812f7c97 77
mfiore 0:bb4e812f7c97 78 fs->check_cb_f = check_cb_f;
mfiore 0:bb4e812f7c97 79
mfiore 0:bb4e812f7c97 80 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 81
mfiore 0:bb4e812f7c97 82 return 0;
mfiore 0:bb4e812f7c97 83 }
mfiore 0:bb4e812f7c97 84
mfiore 0:bb4e812f7c97 85 void SPIFFS_unmount(spiffs *fs) {
mfiore 0:bb4e812f7c97 86 if (!SPIFFS_CHECK_MOUNT(fs)) return;
mfiore 0:bb4e812f7c97 87 SPIFFS_LOCK(fs);
mfiore 0:bb4e812f7c97 88 int i;
mfiore 0:bb4e812f7c97 89 spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
mfiore 0:bb4e812f7c97 90 for (i = 0; i < fs->fd_count; i++) {
mfiore 0:bb4e812f7c97 91 spiffs_fd *cur_fd = &fds[i];
mfiore 0:bb4e812f7c97 92 if (cur_fd->file_nbr != 0) {
mfiore 0:bb4e812f7c97 93 #if SPIFFS_CACHE
mfiore 0:bb4e812f7c97 94 (void)spiffs_fflush_cache(fs, cur_fd->file_nbr);
mfiore 0:bb4e812f7c97 95 #endif
mfiore 0:bb4e812f7c97 96 spiffs_fd_return(fs, cur_fd->file_nbr);
mfiore 0:bb4e812f7c97 97 }
mfiore 0:bb4e812f7c97 98 }
mfiore 0:bb4e812f7c97 99 fs->block_count = 0;
mfiore 0:bb4e812f7c97 100 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 101 }
mfiore 0:bb4e812f7c97 102
mfiore 0:bb4e812f7c97 103 s32_t SPIFFS_errno(spiffs *fs) {
Leon Lindenfelser 3:9adcf49bb77d 104 return fs->err_code;
mfiore 0:bb4e812f7c97 105 }
mfiore 0:bb4e812f7c97 106
mfiore 0:bb4e812f7c97 107 s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode) {
mfiore 0:bb4e812f7c97 108 SPIFFS_API_CHECK_MOUNT(fs);
mfiore 0:bb4e812f7c97 109 SPIFFS_LOCK(fs);
mfiore 0:bb4e812f7c97 110 spiffs_obj_id obj_id;
mfiore 0:bb4e812f7c97 111 s32_t res;
mfiore 0:bb4e812f7c97 112
mfiore 0:bb4e812f7c97 113 res = spiffs_obj_lu_find_free_obj_id(fs, &obj_id);
mfiore 0:bb4e812f7c97 114 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 115 res = spiffs_object_create(fs, obj_id, (u8_t*)path, SPIFFS_TYPE_FILE, 0);
mfiore 0:bb4e812f7c97 116 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 117 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 118 return 0;
mfiore 0:bb4e812f7c97 119 }
mfiore 0:bb4e812f7c97 120
mfiore 0:bb4e812f7c97 121 spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode mode) {
mfiore 0:bb4e812f7c97 122 SPIFFS_API_CHECK_MOUNT(fs);
mfiore 0:bb4e812f7c97 123 SPIFFS_LOCK(fs);
mfiore 0:bb4e812f7c97 124
mfiore 0:bb4e812f7c97 125 spiffs_fd *fd;
mfiore 0:bb4e812f7c97 126 spiffs_page_ix pix;
mfiore 0:bb4e812f7c97 127
mfiore 0:bb4e812f7c97 128 s32_t res = spiffs_fd_find_new(fs, &fd);
mfiore 0:bb4e812f7c97 129 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 130
mfiore 0:bb4e812f7c97 131 res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)path, &pix);
mfiore 0:bb4e812f7c97 132 if ((flags & SPIFFS_CREAT) == 0) {
mfiore 0:bb4e812f7c97 133 if (res < SPIFFS_OK) {
mfiore 0:bb4e812f7c97 134 spiffs_fd_return(fs, fd->file_nbr);
mfiore 0:bb4e812f7c97 135 }
mfiore 0:bb4e812f7c97 136 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 137 }
mfiore 0:bb4e812f7c97 138
mfiore 0:bb4e812f7c97 139 if ((flags & SPIFFS_CREAT) && res == SPIFFS_ERR_NOT_FOUND) {
mfiore 0:bb4e812f7c97 140 spiffs_obj_id obj_id;
mfiore 0:bb4e812f7c97 141 res = spiffs_obj_lu_find_free_obj_id(fs, &obj_id);
mfiore 0:bb4e812f7c97 142 if (res < SPIFFS_OK) {
mfiore 0:bb4e812f7c97 143 spiffs_fd_return(fs, fd->file_nbr);
mfiore 0:bb4e812f7c97 144 }
mfiore 0:bb4e812f7c97 145 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 146 res = spiffs_object_create(fs, obj_id, (u8_t*)path, SPIFFS_TYPE_FILE, &pix);
mfiore 0:bb4e812f7c97 147 if (res < SPIFFS_OK) {
mfiore 0:bb4e812f7c97 148 spiffs_fd_return(fs, fd->file_nbr);
mfiore 0:bb4e812f7c97 149 }
mfiore 0:bb4e812f7c97 150 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 151 flags &= ~SPIFFS_TRUNC;
mfiore 0:bb4e812f7c97 152 } else {
mfiore 0:bb4e812f7c97 153 if (res < SPIFFS_OK) {
mfiore 0:bb4e812f7c97 154 spiffs_fd_return(fs, fd->file_nbr);
mfiore 0:bb4e812f7c97 155 }
mfiore 0:bb4e812f7c97 156 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 157 }
mfiore 0:bb4e812f7c97 158 res = spiffs_object_open_by_page(fs, pix, fd, flags, flags);
mfiore 0:bb4e812f7c97 159 if (res < SPIFFS_OK) {
mfiore 0:bb4e812f7c97 160 spiffs_fd_return(fs, fd->file_nbr);
mfiore 0:bb4e812f7c97 161 }
mfiore 0:bb4e812f7c97 162 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 163 if (flags & SPIFFS_TRUNC) {
mfiore 0:bb4e812f7c97 164 res = spiffs_object_truncate(fd, 0, 0);
mfiore 0:bb4e812f7c97 165 if (res < SPIFFS_OK) {
mfiore 0:bb4e812f7c97 166 spiffs_fd_return(fs, fd->file_nbr);
mfiore 0:bb4e812f7c97 167 }
mfiore 0:bb4e812f7c97 168 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 169 }
mfiore 0:bb4e812f7c97 170
mfiore 0:bb4e812f7c97 171 fd->fdoffset = 0;
mfiore 0:bb4e812f7c97 172
mfiore 0:bb4e812f7c97 173 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 174
mfiore 0:bb4e812f7c97 175 return fd->file_nbr;
mfiore 0:bb4e812f7c97 176 }
mfiore 0:bb4e812f7c97 177
mfiore 0:bb4e812f7c97 178 s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
mfiore 0:bb4e812f7c97 179 SPIFFS_API_CHECK_MOUNT(fs);
mfiore 0:bb4e812f7c97 180 SPIFFS_LOCK(fs);
mfiore 0:bb4e812f7c97 181
mfiore 0:bb4e812f7c97 182 spiffs_fd *fd;
mfiore 0:bb4e812f7c97 183 s32_t res;
mfiore 0:bb4e812f7c97 184
mfiore 0:bb4e812f7c97 185 res = spiffs_fd_get(fs, fh, &fd);
mfiore 0:bb4e812f7c97 186 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 187
mfiore 0:bb4e812f7c97 188 if ((fd->flags & SPIFFS_RDONLY) == 0) {
mfiore 0:bb4e812f7c97 189 res = SPIFFS_ERR_NOT_READABLE;
mfiore 0:bb4e812f7c97 190 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 191 }
mfiore 0:bb4e812f7c97 192
mfiore 0:bb4e812f7c97 193 #if SPIFFS_CACHE_WR
mfiore 0:bb4e812f7c97 194 spiffs_fflush_cache(fs, fh);
mfiore 0:bb4e812f7c97 195 #endif
mfiore 0:bb4e812f7c97 196
mfiore 0:bb4e812f7c97 197 if (fd->fdoffset + len >= fd->size) {
mfiore 0:bb4e812f7c97 198 // reading beyond file size
mfiore 0:bb4e812f7c97 199 s32_t avail = fd->size - fd->fdoffset;
mfiore 0:bb4e812f7c97 200 if (avail <= 0) {
mfiore 0:bb4e812f7c97 201 SPIFFS_API_CHECK_RES_UNLOCK(fs, SPIFFS_ERR_END_OF_OBJECT);
mfiore 0:bb4e812f7c97 202 }
mfiore 0:bb4e812f7c97 203 res = spiffs_object_read(fd, fd->fdoffset, avail, (u8_t*)buf);
mfiore 0:bb4e812f7c97 204 if (res == SPIFFS_ERR_END_OF_OBJECT) {
mfiore 0:bb4e812f7c97 205 fd->fdoffset += avail;
mfiore 0:bb4e812f7c97 206 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 207 return avail;
mfiore 0:bb4e812f7c97 208 } else {
mfiore 0:bb4e812f7c97 209 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 210 }
mfiore 0:bb4e812f7c97 211 } else {
mfiore 0:bb4e812f7c97 212 // reading within file size
mfiore 0:bb4e812f7c97 213 res = spiffs_object_read(fd, fd->fdoffset, len, (u8_t*)buf);
mfiore 0:bb4e812f7c97 214 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 215 }
mfiore 0:bb4e812f7c97 216 fd->fdoffset += len;
mfiore 0:bb4e812f7c97 217
mfiore 0:bb4e812f7c97 218 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 219
mfiore 0:bb4e812f7c97 220 return len;
mfiore 0:bb4e812f7c97 221 }
mfiore 0:bb4e812f7c97 222
mfiore 0:bb4e812f7c97 223 static s32_t spiffs_hydro_write(spiffs *fs, spiffs_fd *fd, void *buf, u32_t offset, s32_t len) {
mfiore 0:bb4e812f7c97 224 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 225 s32_t remaining = len;
mfiore 0:bb4e812f7c97 226 if (fd->size != SPIFFS_UNDEFINED_LEN && offset < fd->size) {
mfiore 0:bb4e812f7c97 227 s32_t m_len = MIN(fd->size - offset, len);
mfiore 0:bb4e812f7c97 228 res = spiffs_object_modify(fd, offset, (u8_t *)buf, m_len);
mfiore 0:bb4e812f7c97 229 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 230 remaining -= m_len;
Mike Fiore 2:de478b250060 231 buf = (u8_t*)buf + m_len;
mfiore 0:bb4e812f7c97 232 offset += m_len;
mfiore 0:bb4e812f7c97 233 }
mfiore 0:bb4e812f7c97 234 if (remaining > 0) {
mfiore 0:bb4e812f7c97 235 res = spiffs_object_append(fd, offset, (u8_t *)buf, remaining);
mfiore 0:bb4e812f7c97 236 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 237 }
mfiore 0:bb4e812f7c97 238 return len;
mfiore 0:bb4e812f7c97 239
mfiore 0:bb4e812f7c97 240 }
mfiore 0:bb4e812f7c97 241
mfiore 0:bb4e812f7c97 242 s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
mfiore 0:bb4e812f7c97 243 SPIFFS_API_CHECK_MOUNT(fs);
mfiore 0:bb4e812f7c97 244 SPIFFS_LOCK(fs);
mfiore 0:bb4e812f7c97 245
mfiore 0:bb4e812f7c97 246 spiffs_fd *fd;
mfiore 0:bb4e812f7c97 247 s32_t res;
mfiore 0:bb4e812f7c97 248 u32_t offset;
mfiore 0:bb4e812f7c97 249
mfiore 0:bb4e812f7c97 250 res = spiffs_fd_get(fs, fh, &fd);
mfiore 0:bb4e812f7c97 251 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 252
mfiore 0:bb4e812f7c97 253 if ((fd->flags & SPIFFS_WRONLY) == 0) {
mfiore 0:bb4e812f7c97 254 res = SPIFFS_ERR_NOT_WRITABLE;
mfiore 0:bb4e812f7c97 255 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 256 }
mfiore 0:bb4e812f7c97 257
mfiore 0:bb4e812f7c97 258 offset = fd->fdoffset;
mfiore 0:bb4e812f7c97 259
mfiore 0:bb4e812f7c97 260 #if SPIFFS_CACHE_WR
mfiore 0:bb4e812f7c97 261 if (fd->cache_page == 0) {
mfiore 0:bb4e812f7c97 262 // see if object id is associated with cache already
mfiore 0:bb4e812f7c97 263 fd->cache_page = spiffs_cache_page_get_by_fd(fs, fd);
mfiore 0:bb4e812f7c97 264 }
mfiore 0:bb4e812f7c97 265 #endif
mfiore 0:bb4e812f7c97 266 if (fd->flags & SPIFFS_APPEND) {
mfiore 0:bb4e812f7c97 267 if (fd->size == SPIFFS_UNDEFINED_LEN) {
mfiore 0:bb4e812f7c97 268 offset = 0;
mfiore 0:bb4e812f7c97 269 } else {
mfiore 0:bb4e812f7c97 270 offset = fd->size;
mfiore 0:bb4e812f7c97 271 }
mfiore 0:bb4e812f7c97 272 #if SPIFFS_CACHE_WR
mfiore 0:bb4e812f7c97 273 if (fd->cache_page) {
mfiore 0:bb4e812f7c97 274 offset = MAX(offset, fd->cache_page->offset + fd->cache_page->size);
mfiore 0:bb4e812f7c97 275 }
mfiore 0:bb4e812f7c97 276 #endif
mfiore 0:bb4e812f7c97 277 }
mfiore 0:bb4e812f7c97 278
mfiore 0:bb4e812f7c97 279 SPIFFS_DBG("SPIFFS_write %i %04x offs:%i len %i\n", fh, fd->obj_id, offset, len);
mfiore 0:bb4e812f7c97 280
mfiore 0:bb4e812f7c97 281 #if SPIFFS_CACHE_WR
mfiore 0:bb4e812f7c97 282 if ((fd->flags & SPIFFS_DIRECT) == 0) {
mfiore 0:bb4e812f7c97 283 if (len < SPIFFS_CFG_LOG_PAGE_SZ(fs)) {
mfiore 0:bb4e812f7c97 284 // small write, try to cache it
mfiore 0:bb4e812f7c97 285 u8_t alloc_cpage = 1;
mfiore 0:bb4e812f7c97 286 if (fd->cache_page) {
mfiore 0:bb4e812f7c97 287 // have a cached page for this fd already, check cache page boundaries
mfiore 0:bb4e812f7c97 288 if (offset < fd->cache_page->offset || // writing before cache
mfiore 0:bb4e812f7c97 289 offset > fd->cache_page->offset + fd->cache_page->size || // writing after cache
mfiore 0:bb4e812f7c97 290 offset + len > fd->cache_page->offset + SPIFFS_CFG_LOG_PAGE_SZ(fs)) // writing beyond cache page
mfiore 0:bb4e812f7c97 291 {
mfiore 0:bb4e812f7c97 292 // boundary violation, write back cache first and allocate new
mfiore 0:bb4e812f7c97 293 SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page %i for fd %i:&04x, boundary viol, offs:%i size:%i\n",
mfiore 0:bb4e812f7c97 294 fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->offset, fd->cache_page->size);
mfiore 0:bb4e812f7c97 295 res = spiffs_hydro_write(fs, fd,
mfiore 0:bb4e812f7c97 296 spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
mfiore 0:bb4e812f7c97 297 fd->cache_page->offset, fd->cache_page->size);
mfiore 0:bb4e812f7c97 298 spiffs_cache_fd_release(fs, fd->cache_page);
mfiore 0:bb4e812f7c97 299 } else {
mfiore 0:bb4e812f7c97 300 // writing within cache
mfiore 0:bb4e812f7c97 301 alloc_cpage = 0;
mfiore 0:bb4e812f7c97 302 }
mfiore 0:bb4e812f7c97 303 }
mfiore 0:bb4e812f7c97 304
mfiore 0:bb4e812f7c97 305 if (alloc_cpage) {
mfiore 0:bb4e812f7c97 306 fd->cache_page = spiffs_cache_page_allocate_by_fd(fs, fd);
mfiore 0:bb4e812f7c97 307 if (fd->cache_page) {
mfiore 0:bb4e812f7c97 308 fd->cache_page->offset = offset;
mfiore 0:bb4e812f7c97 309 fd->cache_page->size = 0;
mfiore 0:bb4e812f7c97 310 SPIFFS_CACHE_DBG("CACHE_WR_ALLO: allocating cache page %i for fd %i:%04x\n",
mfiore 0:bb4e812f7c97 311 fd->cache_page->ix, fd->file_nbr, fd->obj_id);
mfiore 0:bb4e812f7c97 312 }
mfiore 0:bb4e812f7c97 313 }
mfiore 0:bb4e812f7c97 314
mfiore 0:bb4e812f7c97 315 if (fd->cache_page) {
mfiore 0:bb4e812f7c97 316 u32_t offset_in_cpage = offset - fd->cache_page->offset;
mfiore 0:bb4e812f7c97 317 SPIFFS_CACHE_DBG("CACHE_WR_WRITE: storing to cache page %i for fd %i:%04x, offs %i:%i len %i\n",
mfiore 0:bb4e812f7c97 318 fd->cache_page->ix, fd->file_nbr, fd->obj_id,
mfiore 0:bb4e812f7c97 319 offset, offset_in_cpage, len);
mfiore 0:bb4e812f7c97 320 spiffs_cache *cache = spiffs_get_cache(fs);
mfiore 0:bb4e812f7c97 321 u8_t *cpage_data = spiffs_get_cache_page(fs, cache, fd->cache_page->ix);
mfiore 0:bb4e812f7c97 322 memcpy(&cpage_data[offset_in_cpage], buf, len);
mfiore 0:bb4e812f7c97 323 fd->cache_page->size = MAX(fd->cache_page->size, offset_in_cpage + len);
mfiore 0:bb4e812f7c97 324 fd->fdoffset += len;
mfiore 0:bb4e812f7c97 325 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 326 return len;
mfiore 0:bb4e812f7c97 327 } else {
mfiore 0:bb4e812f7c97 328 res = spiffs_hydro_write(fs, fd, buf, offset, len);
mfiore 0:bb4e812f7c97 329 SPIFFS_API_CHECK_RES(fs, res);
mfiore 0:bb4e812f7c97 330 fd->fdoffset += len;
mfiore 0:bb4e812f7c97 331 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 332 return res;
mfiore 0:bb4e812f7c97 333 }
mfiore 0:bb4e812f7c97 334 } else {
mfiore 0:bb4e812f7c97 335 // big write, no need to cache it - but first check if there is a cached write already
mfiore 0:bb4e812f7c97 336 if (fd->cache_page) {
mfiore 0:bb4e812f7c97 337 // write back cache first
mfiore 0:bb4e812f7c97 338 SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page %i for fd %i:%04x, big write, offs:%i size:%i\n",
mfiore 0:bb4e812f7c97 339 fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->offset, fd->cache_page->size);
mfiore 0:bb4e812f7c97 340 res = spiffs_hydro_write(fs, fd,
mfiore 0:bb4e812f7c97 341 spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
mfiore 0:bb4e812f7c97 342 fd->cache_page->offset, fd->cache_page->size);
mfiore 0:bb4e812f7c97 343 spiffs_cache_fd_release(fs, fd->cache_page);
mfiore 0:bb4e812f7c97 344 res = spiffs_hydro_write(fs, fd, buf, offset, len);
mfiore 0:bb4e812f7c97 345 SPIFFS_API_CHECK_RES(fs, res);
mfiore 0:bb4e812f7c97 346 }
mfiore 0:bb4e812f7c97 347 }
mfiore 0:bb4e812f7c97 348 }
mfiore 0:bb4e812f7c97 349 #endif
mfiore 0:bb4e812f7c97 350
mfiore 0:bb4e812f7c97 351 res = spiffs_hydro_write(fs, fd, buf, offset, len);
mfiore 0:bb4e812f7c97 352 SPIFFS_API_CHECK_RES(fs, res);
mfiore 0:bb4e812f7c97 353 fd->fdoffset += len;
mfiore 0:bb4e812f7c97 354
mfiore 0:bb4e812f7c97 355 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 356
mfiore 0:bb4e812f7c97 357 return res;
mfiore 0:bb4e812f7c97 358 }
mfiore 0:bb4e812f7c97 359
mfiore 0:bb4e812f7c97 360 s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
mfiore 0:bb4e812f7c97 361 SPIFFS_API_CHECK_MOUNT(fs);
mfiore 0:bb4e812f7c97 362 SPIFFS_LOCK(fs);
mfiore 0:bb4e812f7c97 363
mfiore 0:bb4e812f7c97 364 spiffs_fd *fd;
mfiore 0:bb4e812f7c97 365 s32_t res;
mfiore 0:bb4e812f7c97 366 res = spiffs_fd_get(fs, fh, &fd);
mfiore 0:bb4e812f7c97 367 SPIFFS_API_CHECK_RES(fs, res);
mfiore 0:bb4e812f7c97 368
mfiore 0:bb4e812f7c97 369 #if SPIFFS_CACHE_WR
mfiore 0:bb4e812f7c97 370 spiffs_fflush_cache(fs, fh);
mfiore 0:bb4e812f7c97 371 #endif
mfiore 0:bb4e812f7c97 372
mfiore 0:bb4e812f7c97 373 switch (whence) {
mfiore 0:bb4e812f7c97 374 case SPIFFS_SEEK_CUR:
mfiore 0:bb4e812f7c97 375 offs = fd->fdoffset+offs;
mfiore 0:bb4e812f7c97 376 break;
mfiore 0:bb4e812f7c97 377 case SPIFFS_SEEK_END:
mfiore 0:bb4e812f7c97 378 offs = (fd->size == SPIFFS_UNDEFINED_LEN ? 0 : fd->size) + offs;
mfiore 0:bb4e812f7c97 379 break;
mfiore 0:bb4e812f7c97 380 }
mfiore 0:bb4e812f7c97 381
mfiore 0:bb4e812f7c97 382 if (offs > fd->size) {
mfiore 0:bb4e812f7c97 383 res = SPIFFS_ERR_END_OF_OBJECT;
mfiore 0:bb4e812f7c97 384 }
mfiore 0:bb4e812f7c97 385 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 386
mfiore 0:bb4e812f7c97 387 spiffs_span_ix data_spix = offs / SPIFFS_DATA_PAGE_SIZE(fs);
mfiore 0:bb4e812f7c97 388 spiffs_span_ix objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
mfiore 0:bb4e812f7c97 389 if (fd->cursor_objix_spix != objix_spix) {
mfiore 0:bb4e812f7c97 390 spiffs_page_ix pix;
mfiore 0:bb4e812f7c97 391 res = spiffs_obj_lu_find_id_and_span(
mfiore 0:bb4e812f7c97 392 fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, objix_spix, 0, &pix);
mfiore 0:bb4e812f7c97 393 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 394 fd->cursor_objix_spix = objix_spix;
mfiore 0:bb4e812f7c97 395 fd->cursor_objix_pix = pix;
mfiore 0:bb4e812f7c97 396 }
mfiore 0:bb4e812f7c97 397 fd->fdoffset = offs;
mfiore 0:bb4e812f7c97 398
mfiore 0:bb4e812f7c97 399 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 400
mfiore 0:bb4e812f7c97 401 return 0;
mfiore 0:bb4e812f7c97 402 }
mfiore 0:bb4e812f7c97 403
mfiore 0:bb4e812f7c97 404 s32_t SPIFFS_remove(spiffs *fs, const char *path) {
mfiore 0:bb4e812f7c97 405 SPIFFS_API_CHECK_MOUNT(fs);
mfiore 0:bb4e812f7c97 406 SPIFFS_LOCK(fs);
mfiore 0:bb4e812f7c97 407
mfiore 0:bb4e812f7c97 408 spiffs_fd *fd;
mfiore 0:bb4e812f7c97 409 spiffs_page_ix pix;
mfiore 0:bb4e812f7c97 410 s32_t res;
mfiore 0:bb4e812f7c97 411
mfiore 0:bb4e812f7c97 412 res = spiffs_fd_find_new(fs, &fd);
mfiore 0:bb4e812f7c97 413 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 414
mfiore 0:bb4e812f7c97 415 res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)path, &pix);
mfiore 0:bb4e812f7c97 416 if (res != SPIFFS_OK) {
mfiore 0:bb4e812f7c97 417 spiffs_fd_return(fs, fd->file_nbr);
mfiore 0:bb4e812f7c97 418 }
mfiore 0:bb4e812f7c97 419 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 420
mfiore 0:bb4e812f7c97 421 res = spiffs_object_open_by_page(fs, pix, fd, 0,0);
mfiore 0:bb4e812f7c97 422 if (res != SPIFFS_OK) {
mfiore 0:bb4e812f7c97 423 spiffs_fd_return(fs, fd->file_nbr);
mfiore 0:bb4e812f7c97 424 }
mfiore 0:bb4e812f7c97 425 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 426
mfiore 0:bb4e812f7c97 427 res = spiffs_object_truncate(fd, 0, 1);
mfiore 0:bb4e812f7c97 428 if (res != SPIFFS_OK) {
mfiore 0:bb4e812f7c97 429 spiffs_fd_return(fs, fd->file_nbr);
mfiore 0:bb4e812f7c97 430 }
mfiore 0:bb4e812f7c97 431 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 432
mfiore 0:bb4e812f7c97 433 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 434 return 0;
mfiore 0:bb4e812f7c97 435 }
mfiore 0:bb4e812f7c97 436
mfiore 0:bb4e812f7c97 437 s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) {
mfiore 0:bb4e812f7c97 438 SPIFFS_API_CHECK_MOUNT(fs);
mfiore 0:bb4e812f7c97 439 SPIFFS_LOCK(fs);
mfiore 0:bb4e812f7c97 440
mfiore 0:bb4e812f7c97 441 spiffs_fd *fd;
mfiore 0:bb4e812f7c97 442 s32_t res;
mfiore 0:bb4e812f7c97 443 res = spiffs_fd_get(fs, fh, &fd);
mfiore 0:bb4e812f7c97 444 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 445
mfiore 0:bb4e812f7c97 446 if ((fd->flags & SPIFFS_WRONLY) == 0) {
mfiore 0:bb4e812f7c97 447 res = SPIFFS_ERR_NOT_WRITABLE;
mfiore 0:bb4e812f7c97 448 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 449 }
mfiore 0:bb4e812f7c97 450
mfiore 0:bb4e812f7c97 451 #if SPIFFS_CACHE_WR
mfiore 0:bb4e812f7c97 452 spiffs_cache_fd_release(fs, fd->cache_page);
mfiore 0:bb4e812f7c97 453 #endif
mfiore 0:bb4e812f7c97 454
mfiore 0:bb4e812f7c97 455 res = spiffs_object_truncate(fd, 0, 1);
mfiore 0:bb4e812f7c97 456
mfiore 0:bb4e812f7c97 457 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 458
mfiore 0:bb4e812f7c97 459 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 460
mfiore 0:bb4e812f7c97 461 return 0;
mfiore 0:bb4e812f7c97 462 }
mfiore 0:bb4e812f7c97 463
Leon Lindenfelser 3:9adcf49bb77d 464
Leon Lindenfelser 3:9adcf49bb77d 465 s32_t SPIFFS_move(spiffs *fs, const char *path, const char *new_path) {
Leon Lindenfelser 3:9adcf49bb77d 466 SPIFFS_API_CHECK_MOUNT(fs);
Leon Lindenfelser 3:9adcf49bb77d 467 SPIFFS_LOCK(fs);
Leon Lindenfelser 3:9adcf49bb77d 468
Leon Lindenfelser 3:9adcf49bb77d 469 spiffs_fd *fd;
Leon Lindenfelser 3:9adcf49bb77d 470 spiffs_page_ix pix;
Leon Lindenfelser 3:9adcf49bb77d 471 spiffs_obj_id obj_id;
Leon Lindenfelser 3:9adcf49bb77d 472 s32_t res;
Leon Lindenfelser 3:9adcf49bb77d 473
Leon Lindenfelser 3:9adcf49bb77d 474 res = spiffs_fd_find_new(fs, &fd);
Leon Lindenfelser 3:9adcf49bb77d 475 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
Leon Lindenfelser 3:9adcf49bb77d 476
Leon Lindenfelser 3:9adcf49bb77d 477 res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)path, &pix);
Leon Lindenfelser 3:9adcf49bb77d 478 if (res != SPIFFS_OK) {
Leon Lindenfelser 3:9adcf49bb77d 479 spiffs_fd_return(fs, fd->file_nbr);
Leon Lindenfelser 3:9adcf49bb77d 480 }
Leon Lindenfelser 3:9adcf49bb77d 481 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
Leon Lindenfelser 3:9adcf49bb77d 482
Leon Lindenfelser 3:9adcf49bb77d 483 u32_t obj_id_addr = SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs , pix)) +
Leon Lindenfelser 3:9adcf49bb77d 484 SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, pix) * sizeof(spiffs_obj_id);
Leon Lindenfelser 3:9adcf49bb77d 485 res =_spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ, fd,
Leon Lindenfelser 3:9adcf49bb77d 486 obj_id_addr, sizeof(spiffs_obj_id), (u8_t *)&obj_id);
Leon Lindenfelser 3:9adcf49bb77d 487 if (res != SPIFFS_OK) {
Leon Lindenfelser 3:9adcf49bb77d 488 spiffs_fd_return(fs, fd->file_nbr);
Leon Lindenfelser 3:9adcf49bb77d 489 }
Leon Lindenfelser 3:9adcf49bb77d 490 SPIFFS_API_CHECK_RES(fs, res);
Leon Lindenfelser 3:9adcf49bb77d 491
Leon Lindenfelser 3:9adcf49bb77d 492 res = spiffs_object_update_index_hdr(fs, fd, obj_id, pix, NULL, new_path, 0, NULL);
Leon Lindenfelser 3:9adcf49bb77d 493 if (res != SPIFFS_OK) {
Leon Lindenfelser 3:9adcf49bb77d 494 spiffs_fd_return(fs, fd->file_nbr);
Leon Lindenfelser 3:9adcf49bb77d 495 }
Leon Lindenfelser 3:9adcf49bb77d 496 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
Leon Lindenfelser 3:9adcf49bb77d 497
Leon Lindenfelser 3:9adcf49bb77d 498 SPIFFS_UNLOCK(fs);
Leon Lindenfelser 3:9adcf49bb77d 499 return 0;
Leon Lindenfelser 3:9adcf49bb77d 500 }
Leon Lindenfelser 3:9adcf49bb77d 501
Leon Lindenfelser 3:9adcf49bb77d 502
mfiore 0:bb4e812f7c97 503 static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spiffs_stat *s) {
mfiore 0:bb4e812f7c97 504 spiffs_page_object_ix_header objix_hdr;
mfiore 0:bb4e812f7c97 505 spiffs_obj_id obj_id;
mfiore 0:bb4e812f7c97 506 s32_t res =_spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ, fh,
mfiore 0:bb4e812f7c97 507 SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&objix_hdr);
mfiore 0:bb4e812f7c97 508 SPIFFS_API_CHECK_RES(fs, res);
mfiore 0:bb4e812f7c97 509
mfiore 0:bb4e812f7c97 510 u32_t obj_id_addr = SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs , pix)) +
mfiore 0:bb4e812f7c97 511 SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, pix) * sizeof(spiffs_obj_id);
mfiore 0:bb4e812f7c97 512 res =_spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ, fh,
mfiore 0:bb4e812f7c97 513 obj_id_addr, sizeof(spiffs_obj_id), (u8_t *)&obj_id);
mfiore 0:bb4e812f7c97 514 SPIFFS_API_CHECK_RES(fs, res);
mfiore 0:bb4e812f7c97 515
mfiore 0:bb4e812f7c97 516 s->obj_id = obj_id;
mfiore 0:bb4e812f7c97 517 s->type = objix_hdr.type;
mfiore 0:bb4e812f7c97 518 s->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size;
mfiore 0:bb4e812f7c97 519 strncpy((char *)s->name, (char *)objix_hdr.name, SPIFFS_OBJ_NAME_LEN);
mfiore 0:bb4e812f7c97 520
mfiore 0:bb4e812f7c97 521 return res;
mfiore 0:bb4e812f7c97 522 }
mfiore 0:bb4e812f7c97 523
mfiore 0:bb4e812f7c97 524 s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s) {
mfiore 0:bb4e812f7c97 525 SPIFFS_API_CHECK_MOUNT(fs);
mfiore 0:bb4e812f7c97 526 SPIFFS_LOCK(fs);
mfiore 0:bb4e812f7c97 527
mfiore 0:bb4e812f7c97 528 s32_t res;
mfiore 0:bb4e812f7c97 529 spiffs_page_ix pix;
mfiore 0:bb4e812f7c97 530
mfiore 0:bb4e812f7c97 531 res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)path, &pix);
mfiore 0:bb4e812f7c97 532 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 533
mfiore 0:bb4e812f7c97 534 res = spiffs_stat_pix(fs, pix, 0, s);
mfiore 0:bb4e812f7c97 535
mfiore 0:bb4e812f7c97 536 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 537
mfiore 0:bb4e812f7c97 538 return res;
mfiore 0:bb4e812f7c97 539 }
mfiore 0:bb4e812f7c97 540
mfiore 0:bb4e812f7c97 541 s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) {
mfiore 0:bb4e812f7c97 542 SPIFFS_API_CHECK_MOUNT(fs);
mfiore 0:bb4e812f7c97 543 SPIFFS_LOCK(fs);
mfiore 0:bb4e812f7c97 544
mfiore 0:bb4e812f7c97 545 spiffs_fd *fd;
mfiore 0:bb4e812f7c97 546 s32_t res;
mfiore 0:bb4e812f7c97 547
mfiore 0:bb4e812f7c97 548 res = spiffs_fd_get(fs, fh, &fd);
mfiore 0:bb4e812f7c97 549 SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
mfiore 0:bb4e812f7c97 550
mfiore 0:bb4e812f7c97 551 #if SPIFFS_CACHE_WR
mfiore 0:bb4e812f7c97 552 spiffs_fflush_cache(fs, fh);
mfiore 0:bb4e812f7c97 553 #endif
mfiore 0:bb4e812f7c97 554
mfiore 0:bb4e812f7c97 555 res = spiffs_stat_pix(fs, fd->objix_hdr_pix, fh, s);
mfiore 0:bb4e812f7c97 556
mfiore 0:bb4e812f7c97 557 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 558
mfiore 0:bb4e812f7c97 559 return res;
mfiore 0:bb4e812f7c97 560 }
mfiore 0:bb4e812f7c97 561
mfiore 0:bb4e812f7c97 562 // Checks if there are any cached writes for the object id associated with
mfiore 0:bb4e812f7c97 563 // given filehandle. If so, these writes are flushed.
mfiore 0:bb4e812f7c97 564 static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
mfiore 0:bb4e812f7c97 565 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 566 #if SPIFFS_CACHE_WR
mfiore 0:bb4e812f7c97 567
mfiore 0:bb4e812f7c97 568 spiffs_fd *fd;
mfiore 0:bb4e812f7c97 569 res = spiffs_fd_get(fs, fh, &fd);
mfiore 0:bb4e812f7c97 570 SPIFFS_API_CHECK_RES(fs, res);
mfiore 0:bb4e812f7c97 571
mfiore 0:bb4e812f7c97 572 if ((fd->flags & SPIFFS_DIRECT) == 0) {
mfiore 0:bb4e812f7c97 573 if (fd->cache_page == 0) {
mfiore 0:bb4e812f7c97 574 // see if object id is associated with cache already
mfiore 0:bb4e812f7c97 575 fd->cache_page = spiffs_cache_page_get_by_fd(fs, fd);
mfiore 0:bb4e812f7c97 576 }
mfiore 0:bb4e812f7c97 577 if (fd->cache_page) {
mfiore 0:bb4e812f7c97 578 SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page %i for fd %i:%04x, flush, offs:%i size:%i\n",
mfiore 0:bb4e812f7c97 579 fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->offset, fd->cache_page->size);
mfiore 0:bb4e812f7c97 580 res = spiffs_hydro_write(fs, fd,
mfiore 0:bb4e812f7c97 581 spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
mfiore 0:bb4e812f7c97 582 fd->cache_page->offset, fd->cache_page->size);
mfiore 0:bb4e812f7c97 583 if (res < SPIFFS_OK) {
Leon Lindenfelser 3:9adcf49bb77d 584 fs->err_code = res;
mfiore 0:bb4e812f7c97 585 }
mfiore 0:bb4e812f7c97 586 spiffs_cache_fd_release(fs, fd->cache_page);
mfiore 0:bb4e812f7c97 587 }
mfiore 0:bb4e812f7c97 588 }
mfiore 0:bb4e812f7c97 589 #endif
mfiore 0:bb4e812f7c97 590
mfiore 0:bb4e812f7c97 591 return res;
mfiore 0:bb4e812f7c97 592 }
mfiore 0:bb4e812f7c97 593
mfiore 0:bb4e812f7c97 594 s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
mfiore 0:bb4e812f7c97 595 SPIFFS_API_CHECK_MOUNT(fs);
mfiore 0:bb4e812f7c97 596 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 597 #if SPIFFS_CACHE_WR
mfiore 0:bb4e812f7c97 598 SPIFFS_LOCK(fs);
mfiore 0:bb4e812f7c97 599 res = spiffs_fflush_cache(fs, fh);
mfiore 0:bb4e812f7c97 600 SPIFFS_API_CHECK_RES_UNLOCK(fs,res);
mfiore 0:bb4e812f7c97 601 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 602 #endif
mfiore 0:bb4e812f7c97 603
mfiore 0:bb4e812f7c97 604 return res;
mfiore 0:bb4e812f7c97 605 }
mfiore 0:bb4e812f7c97 606
mfiore 0:bb4e812f7c97 607 void SPIFFS_close(spiffs *fs, spiffs_file fh) {
mfiore 0:bb4e812f7c97 608 if (!SPIFFS_CHECK_MOUNT(fs)) {
Leon Lindenfelser 3:9adcf49bb77d 609 fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
mfiore 0:bb4e812f7c97 610 return;
mfiore 0:bb4e812f7c97 611 }
mfiore 0:bb4e812f7c97 612 SPIFFS_LOCK(fs);
mfiore 0:bb4e812f7c97 613
mfiore 0:bb4e812f7c97 614 #if SPIFFS_CACHE
mfiore 0:bb4e812f7c97 615 spiffs_fflush_cache(fs, fh);
mfiore 0:bb4e812f7c97 616 #endif
mfiore 0:bb4e812f7c97 617 spiffs_fd_return(fs, fh);
mfiore 0:bb4e812f7c97 618
mfiore 0:bb4e812f7c97 619 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 620 }
mfiore 0:bb4e812f7c97 621
mfiore 0:bb4e812f7c97 622 spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d) {
mfiore 0:bb4e812f7c97 623 if (!SPIFFS_CHECK_MOUNT(fs)) {
Leon Lindenfelser 3:9adcf49bb77d 624 fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
mfiore 0:bb4e812f7c97 625 return 0;
mfiore 0:bb4e812f7c97 626 }
mfiore 0:bb4e812f7c97 627 d->fs = fs;
mfiore 0:bb4e812f7c97 628 d->block = 0;
mfiore 0:bb4e812f7c97 629 d->entry = 0;
mfiore 0:bb4e812f7c97 630 return d;
mfiore 0:bb4e812f7c97 631 }
mfiore 0:bb4e812f7c97 632
mfiore 0:bb4e812f7c97 633 static s32_t spiffs_read_dir_v(
mfiore 0:bb4e812f7c97 634 spiffs *fs,
mfiore 0:bb4e812f7c97 635 spiffs_obj_id obj_id,
mfiore 0:bb4e812f7c97 636 spiffs_block_ix bix,
mfiore 0:bb4e812f7c97 637 int ix_entry,
mfiore 0:bb4e812f7c97 638 u32_t user_data,
mfiore 0:bb4e812f7c97 639 void *user_p) {
mfiore 0:bb4e812f7c97 640 s32_t res;
mfiore 0:bb4e812f7c97 641 spiffs_page_object_ix_header objix_hdr;
mfiore 0:bb4e812f7c97 642 if (obj_id == SPIFFS_OBJ_ID_FREE || obj_id == SPIFFS_OBJ_ID_DELETED ||
mfiore 0:bb4e812f7c97 643 (obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0) {
mfiore 0:bb4e812f7c97 644 return SPIFFS_VIS_COUNTINUE;
mfiore 0:bb4e812f7c97 645 }
mfiore 0:bb4e812f7c97 646
mfiore 0:bb4e812f7c97 647 spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry);
mfiore 0:bb4e812f7c97 648 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 649 0, SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&objix_hdr);
mfiore 0:bb4e812f7c97 650 if (res != SPIFFS_OK) return res;
mfiore 0:bb4e812f7c97 651 if ((obj_id & SPIFFS_OBJ_ID_IX_FLAG) &&
mfiore 0:bb4e812f7c97 652 objix_hdr.p_hdr.span_ix == 0 &&
mfiore 0:bb4e812f7c97 653 (objix_hdr.p_hdr.flags& (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) ==
mfiore 0:bb4e812f7c97 654 (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) {
mfiore 0:bb4e812f7c97 655 struct spiffs_dirent *e = (struct spiffs_dirent *)user_p;
mfiore 0:bb4e812f7c97 656 e->obj_id = obj_id;
mfiore 0:bb4e812f7c97 657 strcpy((char *)e->name, (char *)objix_hdr.name);
mfiore 0:bb4e812f7c97 658 e->type = objix_hdr.type;
mfiore 0:bb4e812f7c97 659 e->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size;
mfiore 0:bb4e812f7c97 660 return SPIFFS_OK;
mfiore 0:bb4e812f7c97 661 }
mfiore 0:bb4e812f7c97 662
mfiore 0:bb4e812f7c97 663 return SPIFFS_VIS_COUNTINUE;
mfiore 0:bb4e812f7c97 664 }
mfiore 0:bb4e812f7c97 665
mfiore 0:bb4e812f7c97 666 struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) {
mfiore 0:bb4e812f7c97 667 if (!SPIFFS_CHECK_MOUNT(d->fs)) {
Leon Lindenfelser 3:9adcf49bb77d 668 d->fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
mfiore 0:bb4e812f7c97 669 return 0;
mfiore 0:bb4e812f7c97 670 }
mfiore 0:bb4e812f7c97 671 SPIFFS_LOCK(fs);
mfiore 0:bb4e812f7c97 672
mfiore 0:bb4e812f7c97 673 spiffs_block_ix bix;
mfiore 0:bb4e812f7c97 674 int entry;
mfiore 0:bb4e812f7c97 675 s32_t res;
mfiore 0:bb4e812f7c97 676 struct spiffs_dirent *ret = 0;
mfiore 0:bb4e812f7c97 677
mfiore 0:bb4e812f7c97 678 res = spiffs_obj_lu_find_entry_visitor(d->fs,
mfiore 0:bb4e812f7c97 679 d->block,
mfiore 0:bb4e812f7c97 680 d->entry,
mfiore 0:bb4e812f7c97 681 SPIFFS_VIS_NO_WRAP,
mfiore 0:bb4e812f7c97 682 0,
mfiore 0:bb4e812f7c97 683 spiffs_read_dir_v,
mfiore 0:bb4e812f7c97 684 0,
mfiore 0:bb4e812f7c97 685 e,
mfiore 0:bb4e812f7c97 686 &bix,
mfiore 0:bb4e812f7c97 687 &entry);
mfiore 0:bb4e812f7c97 688 if (res == SPIFFS_OK) {
mfiore 0:bb4e812f7c97 689 d->block = bix;
mfiore 0:bb4e812f7c97 690 d->entry = entry + 1;
mfiore 0:bb4e812f7c97 691 ret = e;
mfiore 0:bb4e812f7c97 692 } else {
Leon Lindenfelser 3:9adcf49bb77d 693 d->fs->err_code = res;
mfiore 0:bb4e812f7c97 694 }
mfiore 0:bb4e812f7c97 695 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 696 return ret;
mfiore 0:bb4e812f7c97 697 }
mfiore 0:bb4e812f7c97 698
mfiore 0:bb4e812f7c97 699 s32_t SPIFFS_closedir(spiffs_DIR *d) {
mfiore 0:bb4e812f7c97 700 SPIFFS_API_CHECK_MOUNT(d->fs);
mfiore 0:bb4e812f7c97 701 return 0;
mfiore 0:bb4e812f7c97 702 }
mfiore 0:bb4e812f7c97 703
mfiore 0:bb4e812f7c97 704 s32_t SPIFFS_check(spiffs *fs) {
mfiore 0:bb4e812f7c97 705 s32_t res;
mfiore 0:bb4e812f7c97 706 SPIFFS_API_CHECK_MOUNT(fs);
mfiore 0:bb4e812f7c97 707 SPIFFS_LOCK(fs);
mfiore 0:bb4e812f7c97 708
mfiore 0:bb4e812f7c97 709 res = spiffs_lookup_consistency_check(fs, 0);
mfiore 0:bb4e812f7c97 710
mfiore 0:bb4e812f7c97 711 res = spiffs_object_index_consistency_check(fs);
mfiore 0:bb4e812f7c97 712
mfiore 0:bb4e812f7c97 713 res = spiffs_page_consistency_check(fs);
mfiore 0:bb4e812f7c97 714
mfiore 0:bb4e812f7c97 715 res = spiffs_obj_lu_scan(fs);
mfiore 0:bb4e812f7c97 716
mfiore 0:bb4e812f7c97 717 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 718 return res;
mfiore 0:bb4e812f7c97 719 }
mfiore 0:bb4e812f7c97 720
mfiore 0:bb4e812f7c97 721 #if SPIFFS_TEST_VISUALISATION
mfiore 0:bb4e812f7c97 722 s32_t SPIFFS_vis(spiffs *fs) {
mfiore 0:bb4e812f7c97 723 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 724 SPIFFS_API_CHECK_MOUNT(fs);
mfiore 0:bb4e812f7c97 725 SPIFFS_LOCK(fs);
mfiore 0:bb4e812f7c97 726
mfiore 0:bb4e812f7c97 727 u32_t entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
mfiore 0:bb4e812f7c97 728 spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
mfiore 0:bb4e812f7c97 729 spiffs_block_ix bix = 0;
mfiore 0:bb4e812f7c97 730
mfiore 0:bb4e812f7c97 731 while (bix < fs->block_count) {
mfiore 0:bb4e812f7c97 732 // check each object lookup page
mfiore 0:bb4e812f7c97 733 int obj_lookup_page = 0;
mfiore 0:bb4e812f7c97 734 int cur_entry = 0;
mfiore 0:bb4e812f7c97 735
mfiore 0:bb4e812f7c97 736 while (res == SPIFFS_OK && obj_lookup_page < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
mfiore 0:bb4e812f7c97 737 int entry_offset = obj_lookup_page * entries_per_page;
mfiore 0:bb4e812f7c97 738 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 739 0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
mfiore 0:bb4e812f7c97 740 // check each entry
mfiore 0:bb4e812f7c97 741 while (res == SPIFFS_OK &&
mfiore 0:bb4e812f7c97 742 cur_entry - entry_offset < entries_per_page && cur_entry < SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
mfiore 0:bb4e812f7c97 743 spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
mfiore 0:bb4e812f7c97 744 if (cur_entry == 0) {
mfiore 0:bb4e812f7c97 745 spiffs_printf("%4i ", bix);
mfiore 0:bb4e812f7c97 746 } else if ((cur_entry & 0x3f) == 0) {
mfiore 0:bb4e812f7c97 747 spiffs_printf(" ");
mfiore 0:bb4e812f7c97 748 }
mfiore 0:bb4e812f7c97 749 if (obj_id == SPIFFS_OBJ_ID_FREE) {
mfiore 0:bb4e812f7c97 750 spiffs_printf(SPIFFS_TEST_VIS_FREE_STR);
mfiore 0:bb4e812f7c97 751 } else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
mfiore 0:bb4e812f7c97 752 spiffs_printf(SPIFFS_TEST_VIS_DELE_STR);
mfiore 0:bb4e812f7c97 753 } else if (obj_id & SPIFFS_OBJ_ID_IX_FLAG){
mfiore 0:bb4e812f7c97 754 spiffs_printf(SPIFFS_TEST_VIS_INDX_STR(obj_id));
mfiore 0:bb4e812f7c97 755 } else {
mfiore 0:bb4e812f7c97 756 spiffs_printf(SPIFFS_TEST_VIS_DATA_STR(obj_id));
mfiore 0:bb4e812f7c97 757 }
mfiore 0:bb4e812f7c97 758 cur_entry++;
mfiore 0:bb4e812f7c97 759 if ((cur_entry & 0x3f) == 0) {
mfiore 0:bb4e812f7c97 760 spiffs_printf("\n");
mfiore 0:bb4e812f7c97 761 }
mfiore 0:bb4e812f7c97 762 } // per entry
mfiore 0:bb4e812f7c97 763 obj_lookup_page++;
mfiore 0:bb4e812f7c97 764 } // per object lookup page
mfiore 0:bb4e812f7c97 765
mfiore 0:bb4e812f7c97 766 spiffs_obj_id erase_count;
mfiore 0:bb4e812f7c97 767 res = _spiffs_rd(fs, SPIFFS_OP_C_READ | SPIFFS_OP_T_OBJ_LU2, 0,
mfiore 0:bb4e812f7c97 768 SPIFFS_ERASE_COUNT_PADDR(fs, bix),
mfiore 0:bb4e812f7c97 769 sizeof(spiffs_obj_id), (u8_t *)&erase_count);
mfiore 0:bb4e812f7c97 770 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 771
mfiore 0:bb4e812f7c97 772 if (erase_count != (spiffs_obj_id)-1) {
mfiore 0:bb4e812f7c97 773 spiffs_printf("\tera_cnt: %i\n", erase_count);
mfiore 0:bb4e812f7c97 774 } else {
mfiore 0:bb4e812f7c97 775 spiffs_printf("\tera_cnt: N/A\n");
mfiore 0:bb4e812f7c97 776 }
mfiore 0:bb4e812f7c97 777
mfiore 0:bb4e812f7c97 778 bix++;
mfiore 0:bb4e812f7c97 779 } // per block
mfiore 0:bb4e812f7c97 780
mfiore 0:bb4e812f7c97 781 spiffs_printf("era_cnt_max: %i\n", fs->max_erase_count);
Leon Lindenfelser 3:9adcf49bb77d 782 spiffs_printf("last_errno: %i\n", fs->err_code);
mfiore 0:bb4e812f7c97 783 spiffs_printf("blocks: %i\n", fs->block_count);
mfiore 0:bb4e812f7c97 784 spiffs_printf("free_blocks: %i\n", fs->free_blocks);
mfiore 0:bb4e812f7c97 785 spiffs_printf("page_alloc: %i\n", fs->stats_p_allocated);
mfiore 0:bb4e812f7c97 786 spiffs_printf("page_delet: %i\n", fs->stats_p_deleted);
mfiore 0:bb4e812f7c97 787
mfiore 0:bb4e812f7c97 788 SPIFFS_UNLOCK(fs);
mfiore 0:bb4e812f7c97 789 return res;
mfiore 0:bb4e812f7c97 790 }
Mike Fiore 2:de478b250060 791 #endif