spiffs.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. #include "c_stdio.h"
  2. #include "platform.h"
  3. #include "spiffs.h"
  4. spiffs fs;
  5. #define LOG_PAGE_SIZE 256
  6. #define LOG_BLOCK_SIZE (INTERNAL_FLASH_SECTOR_SIZE * 2)
  7. #define LOG_BLOCK_SIZE_SMALL_FS (INTERNAL_FLASH_SECTOR_SIZE)
  8. #define MIN_BLOCKS_FS 4
  9. static u8_t spiffs_work_buf[LOG_PAGE_SIZE*2];
  10. static u8_t spiffs_fds[32*4];
  11. #if SPIFFS_CACHE
  12. static u8_t spiffs_cache[(LOG_PAGE_SIZE+32)*2];
  13. #endif
  14. static s32_t my_spiffs_read(u32_t addr, u32_t size, u8_t *dst) {
  15. platform_flash_read(dst, addr, size);
  16. return SPIFFS_OK;
  17. }
  18. static s32_t my_spiffs_write(u32_t addr, u32_t size, u8_t *src) {
  19. platform_flash_write(src, addr, size);
  20. return SPIFFS_OK;
  21. }
  22. static s32_t my_spiffs_erase(u32_t addr, u32_t size) {
  23. u32_t sect_first = platform_flash_get_sector_of_address(addr);
  24. u32_t sect_last = sect_first;
  25. while( sect_first <= sect_last )
  26. if( platform_flash_erase_sector( sect_first ++ ) == PLATFORM_ERR )
  27. return SPIFFS_ERR_INTERNAL;
  28. return SPIFFS_OK;
  29. }
  30. void myspiffs_check_callback(spiffs_check_type type, spiffs_check_report report, u32_t arg1, u32_t arg2){
  31. // if(SPIFFS_CHECK_PROGRESS == report) return;
  32. // NODE_ERR("type: %d, report: %d, arg1: %d, arg2: %d\n", type, report, arg1, arg2);
  33. }
  34. /*******************
  35. The W25Q32BV array is organized into 16,384 programmable pages of 256-bytes each. Up to 256 bytes can be programmed at a time. 
  36. Pages can be erased in groups of 16 (4KB sector erase), groups of 128 (32KB block erase), groups of 256 (64KB block erase) or 
  37. the entire chip (chip erase). The W25Q32BV has 1,024 erasable sectors and 64 erasable blocks respectively. 
  38. The small 4KB sectors allow for greater flexibility in applications that require data and parameter storage. 
  39. ********************/
  40. static bool myspiffs_set_location(spiffs_config *cfg, int align, int offset, int block_size) {
  41. #ifdef SPIFFS_FIXED_LOCATION
  42. cfg->phys_addr = (SPIFFS_FIXED_LOCATION + block_size - 1) & ~(block_size-1);
  43. #else
  44. cfg->phys_addr = ( u32_t )platform_flash_get_first_free_block_address( NULL ) + offset;
  45. cfg->phys_addr = (cfg->phys_addr + align - 1) & ~(align - 1);
  46. #endif
  47. #ifdef SPIFFS_SIZE_1M_BOUNDARY
  48. cfg->phys_size = ((0x100000 - 16384 - ( ( u32_t )cfg->phys_addr )) & ~(block_size - 1)) & 0xfffff;
  49. #else
  50. cfg->phys_size = (INTERNAL_FLASH_SIZE - ( ( u32_t )cfg->phys_addr )) & ~(block_size - 1);
  51. #endif
  52. if ((int) cfg->phys_size < 0) {
  53. return FALSE;
  54. }
  55. cfg->log_block_size = block_size;
  56. return (cfg->phys_size / block_size) >= MIN_BLOCKS_FS;
  57. }
  58. /*
  59. * Returns TRUE if FS was found
  60. * align must be a power of two
  61. */
  62. static bool myspiffs_set_cfg(spiffs_config *cfg, int align, int offset, bool force_create) {
  63. cfg->phys_erase_block = INTERNAL_FLASH_SECTOR_SIZE; // according to datasheet
  64. cfg->log_page_size = LOG_PAGE_SIZE; // as we said
  65. cfg->hal_read_f = my_spiffs_read;
  66. cfg->hal_write_f = my_spiffs_write;
  67. cfg->hal_erase_f = my_spiffs_erase;
  68. if (!myspiffs_set_location(cfg, align, offset, LOG_BLOCK_SIZE)) {
  69. if (!myspiffs_set_location(cfg, align, offset, LOG_BLOCK_SIZE_SMALL_FS)) {
  70. return FALSE;
  71. }
  72. }
  73. NODE_DBG("fs.start:%x,max:%x\n",cfg->phys_addr,cfg->phys_size);
  74. #ifdef SPIFFS_USE_MAGIC_LENGTH
  75. if (force_create) {
  76. return TRUE;
  77. }
  78. int size = SPIFFS_probe_fs(cfg);
  79. if (size > 0 && size < cfg->phys_size) {
  80. NODE_DBG("Overriding size:%x\n",size);
  81. cfg->phys_size = size;
  82. }
  83. if (size > 0) {
  84. return TRUE;
  85. }
  86. return FALSE;
  87. #else
  88. return TRUE;
  89. #endif
  90. }
  91. static bool myspiffs_find_cfg(spiffs_config *cfg, bool force_create) {
  92. int i;
  93. if (!force_create) {
  94. #ifdef SPIFFS_FIXED_LOCATION
  95. if (myspiffs_set_cfg(cfg, 0, 0, FALSE)) {
  96. return TRUE;
  97. }
  98. #else
  99. if (INTERNAL_FLASH_SIZE >= 700000) {
  100. for (i = 0; i < 8; i++) {
  101. if (myspiffs_set_cfg(cfg, 0x10000, 0x10000 * i, FALSE)) {
  102. return TRUE;
  103. }
  104. }
  105. }
  106. for (i = 0; i < 8; i++) {
  107. if (myspiffs_set_cfg(cfg, LOG_BLOCK_SIZE, LOG_BLOCK_SIZE * i, FALSE)) {
  108. return TRUE;
  109. }
  110. }
  111. #endif
  112. }
  113. // No existing file system -- set up for a format
  114. if (INTERNAL_FLASH_SIZE >= 700000) {
  115. myspiffs_set_cfg(cfg, 0x10000, 0x10000, TRUE);
  116. #ifndef SPIFFS_MAX_FILESYSTEM_SIZE
  117. if (cfg->phys_size < 400000) {
  118. // Don't waste so much in alignment
  119. myspiffs_set_cfg(cfg, LOG_BLOCK_SIZE, LOG_BLOCK_SIZE * 4, TRUE);
  120. }
  121. #endif
  122. } else {
  123. myspiffs_set_cfg(cfg, LOG_BLOCK_SIZE, 0, TRUE);
  124. }
  125. #ifdef SPIFFS_MAX_FILESYSTEM_SIZE
  126. if (cfg->phys_size > SPIFFS_MAX_FILESYSTEM_SIZE) {
  127. cfg->phys_size = (SPIFFS_MAX_FILESYSTEM_SIZE) & ~(cfg->log_block_size - 1);
  128. }
  129. #endif
  130. return FALSE;
  131. }
  132. static bool myspiffs_mount_internal(bool force_mount) {
  133. spiffs_config cfg;
  134. if (!myspiffs_find_cfg(&cfg, force_mount) && !force_mount) {
  135. return FALSE;
  136. }
  137. fs.err_code = 0;
  138. int res = SPIFFS_mount(&fs,
  139. &cfg,
  140. spiffs_work_buf,
  141. spiffs_fds,
  142. sizeof(spiffs_fds),
  143. #if SPIFFS_CACHE
  144. spiffs_cache,
  145. sizeof(spiffs_cache),
  146. #else
  147. 0, 0,
  148. #endif
  149. // myspiffs_check_callback);
  150. 0);
  151. NODE_DBG("mount res: %d, %d\n", res, fs.err_code);
  152. return res == SPIFFS_OK;
  153. }
  154. bool myspiffs_mount() {
  155. return myspiffs_mount_internal(FALSE);
  156. }
  157. void myspiffs_unmount() {
  158. SPIFFS_unmount(&fs);
  159. }
  160. // FS formatting function
  161. // Returns 1 if OK, 0 for error
  162. int myspiffs_format( void )
  163. {
  164. SPIFFS_unmount(&fs);
  165. myspiffs_mount_internal(TRUE);
  166. SPIFFS_unmount(&fs);
  167. NODE_DBG("Formatting: size 0x%x, addr 0x%x\n", fs.cfg.phys_size, fs.cfg.phys_addr);
  168. if (SPIFFS_format(&fs) < 0) {
  169. return 0;
  170. }
  171. return myspiffs_mount();
  172. }
  173. int myspiffs_check( void )
  174. {
  175. // ets_wdt_disable();
  176. // int res = (int)SPIFFS_check(&fs);
  177. // ets_wdt_enable();
  178. // return res;
  179. }
  180. int myspiffs_open(const char *name, int flags){
  181. return (int)SPIFFS_open(&fs, (char *)name, (spiffs_flags)flags, 0);
  182. }
  183. int myspiffs_close( int fd ){
  184. return SPIFFS_close(&fs, (spiffs_file)fd);
  185. }
  186. size_t myspiffs_write( int fd, const void* ptr, size_t len ){
  187. #if 0
  188. if(fd==c_stdout || fd==c_stderr){
  189. uart0_tx_buffer((u8_t*)ptr, len);
  190. return len;
  191. }
  192. #endif
  193. int res = SPIFFS_write(&fs, (spiffs_file)fd, (void *)ptr, len);
  194. if (res < 0) {
  195. NODE_DBG("write errno %i\n", SPIFFS_errno(&fs));
  196. return 0;
  197. }
  198. return res;
  199. }
  200. size_t myspiffs_read( int fd, void* ptr, size_t len){
  201. int res = SPIFFS_read(&fs, (spiffs_file)fd, ptr, len);
  202. if (res < 0) {
  203. NODE_DBG("read errno %i\n", SPIFFS_errno(&fs));
  204. return 0;
  205. }
  206. return res;
  207. }
  208. int myspiffs_lseek( int fd, int off, int whence ){
  209. return SPIFFS_lseek(&fs, (spiffs_file)fd, off, whence);
  210. }
  211. int myspiffs_eof( int fd ){
  212. return SPIFFS_eof(&fs, (spiffs_file)fd);
  213. }
  214. int myspiffs_tell( int fd ){
  215. return SPIFFS_tell(&fs, (spiffs_file)fd);
  216. }
  217. int myspiffs_getc( int fd ){
  218. unsigned char c = 0xFF;
  219. int res;
  220. if(!myspiffs_eof(fd)){
  221. res = SPIFFS_read(&fs, (spiffs_file)fd, &c, 1);
  222. if (res != 1) {
  223. NODE_DBG("getc errno %i\n", SPIFFS_errno(&fs));
  224. return (int)EOF;
  225. } else {
  226. return (int)c;
  227. }
  228. }
  229. return (int)EOF;
  230. }
  231. int myspiffs_ungetc( int c, int fd ){
  232. return SPIFFS_lseek(&fs, (spiffs_file)fd, -1, SEEK_CUR);
  233. }
  234. int myspiffs_flush( int fd ){
  235. return SPIFFS_fflush(&fs, (spiffs_file)fd);
  236. }
  237. int myspiffs_error( int fd ){
  238. return SPIFFS_errno(&fs);
  239. }
  240. void myspiffs_clearerr( int fd ){
  241. SPIFFS_clearerr(&fs);
  242. }
  243. int myspiffs_rename( const char *old, const char *newname ){
  244. return SPIFFS_rename(&fs, (char *)old, (char *)newname);
  245. }
  246. size_t myspiffs_size( int fd ){
  247. int32_t curpos = SPIFFS_tell(&fs, (spiffs_file) fd);
  248. int32_t size = SPIFFS_lseek(&fs, (spiffs_file) fd, SPIFFS_SEEK_END, 0);
  249. (void) SPIFFS_lseek(&fs, (spiffs_file) fd, SPIFFS_SEEK_SET, curpos);
  250. return size;
  251. }
  252. #if 0
  253. void test_spiffs() {
  254. char buf[12];
  255. // Surely, I've mounted spiffs before entering here
  256. spiffs_file fd = SPIFFS_open(&fs, "my_file", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0);
  257. if (SPIFFS_write(&fs, fd, (u8_t *)"Hello world", 12) < 0) NODE_DBG("errno %i\n", SPIFFS_errno(&fs));
  258. SPIFFS_close(&fs, fd);
  259. fd = SPIFFS_open(&fs, "my_file", SPIFFS_RDWR, 0);
  260. if (SPIFFS_read(&fs, fd, (u8_t *)buf, 12) < 0) NODE_DBG("errno %i\n", SPIFFS_errno(&fs));
  261. SPIFFS_close(&fs, fd);
  262. NODE_DBG("--> %s <--\n", buf);
  263. }
  264. #endif