Nuvoton
/
NuMaker-mbed-SD-FileSystem-example
NuMaker SD-File-System with SD mode
main.cpp@27:48b42429011a, 2022-03-11 (annotated)
- 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?
User | Revision | Line number | New 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 |