NuMaker SD-File-System with SD mode

Committer:
ccli8
Date:
Fri Mar 11 14:09:54 2022 +0800
Revision:
27:48b42429011a
Parent:
25:1d348ccfc209
Enable erase() for no file system format

NUSD, like SD, is not flash and doesn't have erase characteristic.
This can cause trouble when a fresh new NUSD (no file system format) is expected.

This commit tries to fix it by:
1. Add flash-simulate layer (FlashSimBlockDevice) on top of NUSD
2. In erase(), whole erase takes too long. Just erase the front so that it will recognize as invalid file system format.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ccli8 21:dfd65207a645 1 /* mbed Microcontroller Library
ccli8 21:dfd65207a645 2 * Copyright (c) 2006-2019 ARM Limited
ccli8 21:dfd65207a645 3 *
ccli8 21:dfd65207a645 4 * Licensed under the Apache License, Version 2.0 (the "License");
ccli8 21:dfd65207a645 5 * you may not use this file except in compliance with the License.
ccli8 21:dfd65207a645 6 * You may obtain a copy of the License at
ccli8 21:dfd65207a645 7 *
ccli8 21:dfd65207a645 8 * http://www.apache.org/licenses/LICENSE-2.0
ccli8 21:dfd65207a645 9 *
ccli8 21:dfd65207a645 10 * Unless required by applicable law or agreed to in writing, software
ccli8 21:dfd65207a645 11 * distributed under the License is distributed on an "AS IS" BASIS,
ccli8 21:dfd65207a645 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ccli8 21:dfd65207a645 13 * See the License for the specific language governing permissions and
ccli8 21:dfd65207a645 14 * limitations under the License.
ccli8 21:dfd65207a645 15 */
ccli8 21:dfd65207a645 16 #include "mbed.h"
ccli8 21:dfd65207a645 17 #include <stdio.h>
ccli8 21:dfd65207a645 18 #include <errno.h>
ccli8 21:dfd65207a645 19
ccli8 21:dfd65207a645 20 #include "NuSDBlockDevice.h"
ccli8 27:48b42429011a 21 #include "FlashSimBlockDevice.h"
ccli8 21:dfd65207a645 22
shliu1 25:1d348ccfc209 23
ccli8 21:dfd65207a645 24 // Maximum number of elements in buffer
ccli8 21:dfd65207a645 25 #define BUFFER_MAX_LEN 10
ccli8 21:dfd65207a645 26
ccli8 21:dfd65207a645 27 // NUSD for block device
ccli8 27:48b42429011a 28 NuSDBlockDevice *bd_ = new NuSDBlockDevice();
ccli8 27:48b42429011a 29 // Add flash-simulate layer on top of NUSD not implementing "erase" characteristic
ccli8 27:48b42429011a 30 FlashSimBlockDevice *bd = new FlashSimBlockDevice(bd_);
ccli8 21:dfd65207a645 31
ccli8 21:dfd65207a645 32 // Instead of the default block device, you can define your own block device.
ccli8 21:dfd65207a645 33 // For example: HeapBlockDevice with size of 2048 bytes, read size 1, write size 1 and erase size 512.
ccli8 21:dfd65207a645 34 // #include "HeapBlockDevice.h"
ccli8 21:dfd65207a645 35 // BlockDevice *bd = new HeapBlockDevice(2048, 1, 1, 512);
ccli8 21:dfd65207a645 36
ccli8 21:dfd65207a645 37
ccli8 23:036c20fd7064 38 // This example uses FAT file system as the default.
ccli8 23:036c20fd7064 39 #include "FATFileSystem.h"
ccli8 23:036c20fd7064 40 FATFileSystem fs("fs");
ccli8 21:dfd65207a645 41
ccli8 23:036c20fd7064 42 // Uncomment in the following two lines and comment out the previous two to use Little file system.
ccli8 23:036c20fd7064 43 //#include "LittleFileSystem.h"
ccli8 23:036c20fd7064 44 //LittleFileSystem fs("fs");
ccli8 21:dfd65207a645 45
ccli8 21:dfd65207a645 46
ccli8 21:dfd65207a645 47 // Set up the button to trigger an erase
ccli8 21:dfd65207a645 48 InterruptIn irq(BUTTON1);
shliu1 25:1d348ccfc209 49
ccli8 21:dfd65207a645 50 void erase() {
ccli8 21:dfd65207a645 51 printf("Initializing the block device... ");
ccli8 21:dfd65207a645 52 fflush(stdout);
ccli8 21:dfd65207a645 53 int err = bd->init();
ccli8 21:dfd65207a645 54 printf("%s\n", (err ? "Fail :(" : "OK"));
ccli8 21:dfd65207a645 55 if (err) {
ccli8 21:dfd65207a645 56 error("error: %s (%d)\n", strerror(-err), err);
ccli8 21:dfd65207a645 57 }
ccli8 21:dfd65207a645 58
ccli8 21:dfd65207a645 59 printf("Erasing the block device... ");
ccli8 21:dfd65207a645 60 fflush(stdout);
ccli8 27:48b42429011a 61 // Whole erase takes too long for SD/NUSD. Just erase the front so that
ccli8 27:48b42429011a 62 // it will recognize as invalid file system format.
ccli8 27:48b42429011a 63 //err = bd->erase(0, bd->size());
ccli8 27:48b42429011a 64 err = bd->erase(0, 1024*64);
ccli8 21:dfd65207a645 65 printf("%s\n", (err ? "Fail :(" : "OK"));
ccli8 21:dfd65207a645 66 if (err) {
ccli8 21:dfd65207a645 67 error("error: %s (%d)\n", strerror(-err), err);
ccli8 21:dfd65207a645 68 }
ccli8 21:dfd65207a645 69
ccli8 21:dfd65207a645 70 printf("Deinitializing the block device... ");
ccli8 21:dfd65207a645 71 fflush(stdout);
ccli8 21:dfd65207a645 72 err = bd->deinit();
ccli8 21:dfd65207a645 73 printf("%s\n", (err ? "Fail :(" : "OK"));
ccli8 21:dfd65207a645 74 if (err) {
ccli8 21:dfd65207a645 75 error("error: %s (%d)\n", strerror(-err), err);
ccli8 21:dfd65207a645 76 }
ccli8 21:dfd65207a645 77 }
ccli8 21:dfd65207a645 78
shliu1 25:1d348ccfc209 79 #if MBED_MAJOR_VERSION >= 6
shliu1 25:1d348ccfc209 80 static auto erase_event = mbed_event_queue()->make_user_allocated_event(erase);
shliu1 25:1d348ccfc209 81 #endif
ccli8 21:dfd65207a645 82
ccli8 21:dfd65207a645 83 // Entry point for the example
ccli8 21:dfd65207a645 84 int main() {
shliu1 25:1d348ccfc209 85 #ifdef MBED_MAJOR_VERSION
shliu1 25:1d348ccfc209 86 printf("Mbed OS version %d.%d.%d\r\n\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);
shliu1 25:1d348ccfc209 87 #endif
ccli8 21:dfd65207a645 88 printf("--- Mbed OS filesystem example ---\n");
ccli8 21:dfd65207a645 89
ccli8 21:dfd65207a645 90 // Setup the erase event on button press, use the event queue
ccli8 21:dfd65207a645 91 // to avoid running in interrupt context
shliu1 25:1d348ccfc209 92 #if MBED_MAJOR_VERSION >= 6
shliu1 25:1d348ccfc209 93 irq.fall(std::ref(erase_event));
shliu1 25:1d348ccfc209 94 #else
ccli8 21:dfd65207a645 95 irq.fall(mbed_event_queue()->event(erase));
shliu1 25:1d348ccfc209 96 #endif
ccli8 21:dfd65207a645 97
ccli8 21:dfd65207a645 98 // Try to mount the filesystem
ccli8 21:dfd65207a645 99 printf("Mounting the filesystem... ");
ccli8 21:dfd65207a645 100 fflush(stdout);
ccli8 21:dfd65207a645 101 int err = fs.mount(bd);
ccli8 21:dfd65207a645 102 printf("%s\n", (err ? "Fail :(" : "OK"));
ccli8 21:dfd65207a645 103 if (err) {
ccli8 21:dfd65207a645 104 // Reformat if we can't mount the filesystem
ccli8 21:dfd65207a645 105 // this should only happen on the first boot
ccli8 21:dfd65207a645 106 printf("No filesystem found, formatting... ");
ccli8 21:dfd65207a645 107 fflush(stdout);
ccli8 21:dfd65207a645 108 err = fs.reformat(bd);
ccli8 21:dfd65207a645 109 printf("%s\n", (err ? "Fail :(" : "OK"));
ccli8 21:dfd65207a645 110 if (err) {
ccli8 21:dfd65207a645 111 error("error: %s (%d)\n", strerror(-err), err);
ccli8 21:dfd65207a645 112 }
ccli8 21:dfd65207a645 113 }
ccli8 21:dfd65207a645 114
ccli8 21:dfd65207a645 115 // Open the numbers file
ccli8 21:dfd65207a645 116 printf("Opening \"/fs/numbers.txt\"... ");
ccli8 21:dfd65207a645 117 fflush(stdout);
ccli8 21:dfd65207a645 118 FILE *f = fopen("/fs/numbers.txt", "r+");
ccli8 21:dfd65207a645 119 printf("%s\n", (!f ? "Fail :(" : "OK"));
ccli8 21:dfd65207a645 120 if (!f) {
ccli8 21:dfd65207a645 121 // Create the numbers file if it doesn't exist
ccli8 21:dfd65207a645 122 printf("No file found, creating a new file... ");
ccli8 21:dfd65207a645 123 fflush(stdout);
ccli8 21:dfd65207a645 124 f = fopen("/fs/numbers.txt", "w+");
ccli8 21:dfd65207a645 125 printf("%s\n", (!f ? "Fail :(" : "OK"));
ccli8 21:dfd65207a645 126 if (!f) {
ccli8 21:dfd65207a645 127 error("error: %s (%d)\n", strerror(errno), -errno);
ccli8 21:dfd65207a645 128 }
ccli8 21:dfd65207a645 129
ccli8 21:dfd65207a645 130 for (int i = 0; i < 10; i++) {
ccli8 21:dfd65207a645 131 printf("\rWriting numbers (%d/%d)... ", i, 10);
ccli8 21:dfd65207a645 132 fflush(stdout);
ccli8 21:dfd65207a645 133 err = fprintf(f, " %d\n", i);
ccli8 21:dfd65207a645 134 if (err < 0) {
ccli8 21:dfd65207a645 135 printf("Fail :(\n");
ccli8 21:dfd65207a645 136 error("error: %s (%d)\n", strerror(errno), -errno);
ccli8 21:dfd65207a645 137 }
ccli8 21:dfd65207a645 138 }
ccli8 21:dfd65207a645 139 printf("\rWriting numbers (%d/%d)... OK\n", 10, 10);
ccli8 21:dfd65207a645 140
ccli8 21:dfd65207a645 141 printf("Seeking file... ");
ccli8 21:dfd65207a645 142 fflush(stdout);
ccli8 21:dfd65207a645 143 err = fseek(f, 0, SEEK_SET);
ccli8 21:dfd65207a645 144 printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
ccli8 21:dfd65207a645 145 if (err < 0) {
ccli8 21:dfd65207a645 146 error("error: %s (%d)\n", strerror(errno), -errno);
ccli8 21:dfd65207a645 147 }
ccli8 21:dfd65207a645 148 }
ccli8 21:dfd65207a645 149
ccli8 21:dfd65207a645 150 // Go through and increment the numbers
ccli8 21:dfd65207a645 151 for (int i = 0; i < 10; i++) {
ccli8 21:dfd65207a645 152 printf("\rIncrementing numbers (%d/%d)... ", i, 10);
ccli8 21:dfd65207a645 153 fflush(stdout);
ccli8 21:dfd65207a645 154
ccli8 21:dfd65207a645 155 // Get current stream position
ccli8 21:dfd65207a645 156 long pos = ftell(f);
ccli8 21:dfd65207a645 157
ccli8 21:dfd65207a645 158 // Parse out the number and increment
ccli8 21:dfd65207a645 159 char buf[BUFFER_MAX_LEN];
ccli8 21:dfd65207a645 160 if (!fgets(buf, BUFFER_MAX_LEN, f)) {
ccli8 21:dfd65207a645 161 error("error: %s (%d)\n", strerror(errno), -errno);
ccli8 21:dfd65207a645 162 }
ccli8 21:dfd65207a645 163 char *endptr;
ccli8 21:dfd65207a645 164 int32_t number = strtol(buf, &endptr, 10);
ccli8 21:dfd65207a645 165 if (
ccli8 21:dfd65207a645 166 (errno == ERANGE) || // The number is too small/large
ccli8 21:dfd65207a645 167 (endptr == buf) || // No character was read
ccli8 21:dfd65207a645 168 (*endptr && *endptr != '\n') // The whole input was not converted
ccli8 21:dfd65207a645 169 ) {
ccli8 21:dfd65207a645 170 continue;
ccli8 21:dfd65207a645 171 }
ccli8 21:dfd65207a645 172 number += 1;
ccli8 21:dfd65207a645 173
ccli8 21:dfd65207a645 174 // Seek to beginning of number
ccli8 21:dfd65207a645 175 fseek(f, pos, SEEK_SET);
ccli8 21:dfd65207a645 176
ccli8 21:dfd65207a645 177 // Store number
shliu1 25:1d348ccfc209 178 fprintf(f, " %d\n", (int)number);
shliu1 25:1d348ccfc209 179
ccli8 21:dfd65207a645 180 // Flush between write and read on same file
ccli8 21:dfd65207a645 181 fflush(f);
ccli8 21:dfd65207a645 182 }
ccli8 21:dfd65207a645 183 printf("\rIncrementing numbers (%d/%d)... OK\n", 10, 10);
ccli8 21:dfd65207a645 184
ccli8 21:dfd65207a645 185 // Close the file which also flushes any cached writes
ccli8 21:dfd65207a645 186 printf("Closing \"/fs/numbers.txt\"... ");
ccli8 21:dfd65207a645 187 fflush(stdout);
ccli8 21:dfd65207a645 188 err = fclose(f);
ccli8 21:dfd65207a645 189 printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
ccli8 21:dfd65207a645 190 if (err < 0) {
ccli8 21:dfd65207a645 191 error("error: %s (%d)\n", strerror(errno), -errno);
ccli8 21:dfd65207a645 192 }
ccli8 21:dfd65207a645 193
ccli8 21:dfd65207a645 194 // Display the root directory
ccli8 21:dfd65207a645 195 printf("Opening the root directory... ");
ccli8 21:dfd65207a645 196 fflush(stdout);
ccli8 21:dfd65207a645 197 DIR *d = opendir("/fs/");
ccli8 21:dfd65207a645 198 printf("%s\n", (!d ? "Fail :(" : "OK"));
ccli8 21:dfd65207a645 199 if (!d) {
ccli8 21:dfd65207a645 200 error("error: %s (%d)\n", strerror(errno), -errno);
ccli8 21:dfd65207a645 201 }
ccli8 21:dfd65207a645 202
ccli8 21:dfd65207a645 203 printf("root directory:\n");
ccli8 21:dfd65207a645 204 while (true) {
ccli8 21:dfd65207a645 205 struct dirent *e = readdir(d);
ccli8 21:dfd65207a645 206 if (!e) {
ccli8 21:dfd65207a645 207 break;
ccli8 21:dfd65207a645 208 }
ccli8 21:dfd65207a645 209
ccli8 21:dfd65207a645 210 printf(" %s\n", e->d_name);
ccli8 21:dfd65207a645 211 }
ccli8 21:dfd65207a645 212
ccli8 21:dfd65207a645 213 printf("Closing the root directory... ");
ccli8 21:dfd65207a645 214 fflush(stdout);
ccli8 21:dfd65207a645 215 err = closedir(d);
ccli8 21:dfd65207a645 216 printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
ccli8 21:dfd65207a645 217 if (err < 0) {
ccli8 21:dfd65207a645 218 error("error: %s (%d)\n", strerror(errno), -errno);
ccli8 21:dfd65207a645 219 }
ccli8 21:dfd65207a645 220
ccli8 21:dfd65207a645 221 // Display the numbers file
ccli8 21:dfd65207a645 222 printf("Opening \"/fs/numbers.txt\"... ");
ccli8 21:dfd65207a645 223 fflush(stdout);
ccli8 21:dfd65207a645 224 f = fopen("/fs/numbers.txt", "r");
ccli8 21:dfd65207a645 225 printf("%s\n", (!f ? "Fail :(" : "OK"));
ccli8 21:dfd65207a645 226 if (!f) {
ccli8 21:dfd65207a645 227 error("error: %s (%d)\n", strerror(errno), -errno);
ccli8 21:dfd65207a645 228 }
ccli8 21:dfd65207a645 229
ccli8 21:dfd65207a645 230 printf("numbers:\n");
ccli8 21:dfd65207a645 231 while (!feof(f)) {
ccli8 21:dfd65207a645 232 int c = fgetc(f);
ccli8 21:dfd65207a645 233 printf("%c", c);
ccli8 21:dfd65207a645 234 }
ccli8 21:dfd65207a645 235
ccli8 21:dfd65207a645 236 printf("\rClosing \"/fs/numbers.txt\"... ");
ccli8 21:dfd65207a645 237 fflush(stdout);
ccli8 21:dfd65207a645 238 err = fclose(f);
ccli8 21:dfd65207a645 239 printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
ccli8 21:dfd65207a645 240 if (err < 0) {
ccli8 21:dfd65207a645 241 error("error: %s (%d)\n", strerror(errno), -errno);
ccli8 21:dfd65207a645 242 }
ccli8 21:dfd65207a645 243
ccli8 21:dfd65207a645 244 // Tidy up
ccli8 21:dfd65207a645 245 printf("Unmounting... ");
ccli8 21:dfd65207a645 246 fflush(stdout);
ccli8 21:dfd65207a645 247 err = fs.unmount();
ccli8 21:dfd65207a645 248 printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
ccli8 21:dfd65207a645 249 if (err < 0) {
ccli8 21:dfd65207a645 250 error("error: %s (%d)\n", strerror(-err), err);
ccli8 21:dfd65207a645 251 }
ccli8 21:dfd65207a645 252
ccli8 21:dfd65207a645 253 printf("Mbed OS filesystem example done!\n");
ccli8 21:dfd65207a645 254 }
ccli8 21:dfd65207a645 255