NuMaker SPI flash-backed file system

Committer:
ccli8
Date:
Wed Apr 29 16:47:46 2020 +0800
Revision:
8:47803c22154e
Parent:
6:5904bcfd7c00
Child:
9:6ce52eb7b6c4
Support bare-metal build

To enable bare-metal build:
mbed compile -m <TARGET> -t <TOOLCHAIN> --app-config mbed_app_baremetal.json

Who changed what in which revision?

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