Nuvoton / Mbed OS NuMaker-mbed-SPIF-FileSystem-example
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2019 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "mbed.h"
00017 #include <stdio.h>
00018 #include <errno.h>
00019 
00020 #include "SPIFBlockDevice.h"
00021 
00022 // Maximum number of elements in buffer
00023 #define BUFFER_MAX_LEN 10
00024 
00025 /* Disable write-protect (/WP) and hold (/HOLD) functions
00026  *
00027  * Excerpt on QE bit of Winbond SPI Flash:
00028  *
00029  * The Quad Enable (QE) bit is a non-volatile read/write bit in the status
00030  * register (S9) that enables Quad SPI operation. When the QE bit is set to
00031  * a 0 state (factory default for part numbers with ordering options “IM”),
00032  * the /HOLD are enabled, the device operates in Standard/Dual SPI modes.
00033  * When the QE bit is set to a 1 (factory fixed default for part numbers with
00034  * ordering options “IQ”), the Quad IO2 and IO3 pins are enabled, and /HOLD
00035  * function is disabled, the device operates in Standard/Dual/Quad SPI modes.
00036  *
00037  * So that we need to disable write-protect and hold functions by driving /WP
00038  * and /HOLD pins to high if QE bit is not set.
00039  */
00040 #if defined(TARGET_NUMAKER_IOT_M467)
00041 /* Can comment out the below lines if QE bit is set, e.g. W25Q32JVSSIQ, or keep them for safe */
00042 DigitalOut onboard_spi_wp(PI_13, 1);
00043 DigitalOut onboard_spi_hold(PI_12, 1);
00044 #elif defined(TARGET_NUMAKER_PFM_M487) || defined(TARGET_NUMAKER_IOT_M487)
00045 DigitalOut onboard_spi_wp(PC_5, 1);
00046 DigitalOut onboard_spi_hold(PC_4, 1);
00047 #endif
00048 
00049 BlockDevice *bd = new SPIFBlockDevice(MBED_CONF_SPIF_DRIVER_SPI_MOSI,
00050                                       MBED_CONF_SPIF_DRIVER_SPI_MISO,
00051                                       MBED_CONF_SPIF_DRIVER_SPI_CLK,
00052                                       MBED_CONF_SPIF_DRIVER_SPI_CS);
00053 
00054 // This example uses LittleFileSystem as the default file system
00055 #include "LittleFileSystem.h"
00056 LittleFileSystem fs("fs");
00057 
00058 // Uncomment the following two lines and comment the previous two to use FAT file system.
00059 // #include "FATFileSystem.h"
00060 // FATFileSystem fs("fs");
00061 
00062 // Support bare-metal build in which RTOS will be absent
00063 #if MBED_CONF_RTOS_PRESENT
00064 // Set up the button to trigger an erase
00065 InterruptIn irq(BUTTON1);
00066 void erase() {
00067     printf("Initializing the block device... ");
00068     fflush(stdout);
00069     int err = bd->init();
00070     printf("%s\n", (err ? "Fail :(" : "OK"));
00071     if (err) {
00072         error("error: %s (%d)\n", strerror(-err), err);
00073     }
00074 
00075     printf("Erasing the block device... ");
00076     fflush(stdout);
00077     err = bd->erase(0, bd->size());
00078     printf("%s\n", (err ? "Fail :(" : "OK"));
00079     if (err) {
00080         error("error: %s (%d)\n", strerror(-err), err);
00081     }
00082 
00083     printf("Deinitializing the block device... ");
00084     fflush(stdout);
00085     err = bd->deinit();
00086     printf("%s\n", (err ? "Fail :(" : "OK"));
00087     if (err) {
00088         error("error: %s (%d)\n", strerror(-err), err);
00089     }
00090 }
00091 #endif
00092 
00093 #if MBED_CONF_RTOS_PRESENT
00094 #if MBED_MAJOR_VERSION >= 6
00095 static auto erase_event = mbed_event_queue()->make_user_allocated_event(erase);
00096 #endif
00097 #endif
00098 
00099 // Entry point for the example
00100 int main() {
00101     printf("--- Mbed OS filesystem example ---\n");
00102 
00103 #if MBED_CONF_RTOS_PRESENT
00104     // Setup the erase event on button press, use the event queue
00105     // to avoid running in interrupt context
00106 #if MBED_MAJOR_VERSION >= 6
00107     irq.fall(std::ref(erase_event));
00108 #else
00109     irq.fall(mbed_event_queue()->event(erase));
00110 #endif
00111 #endif
00112 
00113     // Try to mount the filesystem
00114     printf("Mounting the filesystem... ");
00115     fflush(stdout);
00116     int err = fs.mount(bd);
00117     printf("%s\n", (err ? "Fail :(" : "OK"));
00118     if (err) {
00119         // Reformat if we can't mount the filesystem
00120         // this should only happen on the first boot
00121         printf("No filesystem found, formatting... ");
00122         fflush(stdout);
00123         err = fs.reformat(bd);
00124         printf("%s\n", (err ? "Fail :(" : "OK"));
00125         if (err) {
00126             error("error: %s (%d)\n", strerror(-err), err);
00127         }
00128     }
00129 
00130     // Open the numbers file
00131     printf("Opening \"/fs/numbers.txt\"... ");
00132     fflush(stdout);
00133     FILE *f = fopen("/fs/numbers.txt", "r+");
00134     printf("%s\n", (!f ? "Fail :(" : "OK"));
00135     if (!f) {
00136         // Create the numbers file if it doesn't exist
00137         printf("No file found, creating a new file... ");
00138         fflush(stdout);
00139         f = fopen("/fs/numbers.txt", "w+");
00140         printf("%s\n", (!f ? "Fail :(" : "OK"));
00141         if (!f) {
00142             error("error: %s (%d)\n", strerror(errno), -errno);
00143         }
00144 
00145         for (int i = 0; i < 10; i++) {
00146             printf("\rWriting numbers (%d/%d)... ", i, 10);
00147             fflush(stdout);
00148             err = fprintf(f, "    %d\n", i);
00149             if (err < 0) {
00150                 printf("Fail :(\n");
00151                 error("error: %s (%d)\n", strerror(errno), -errno);
00152             }
00153         }
00154         printf("\rWriting numbers (%d/%d)... OK\n", 10, 10);
00155 
00156         printf("Seeking file... ");
00157         fflush(stdout);
00158         err = fseek(f, 0, SEEK_SET);
00159         printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
00160         if (err < 0) {
00161             error("error: %s (%d)\n", strerror(errno), -errno);
00162         }
00163     }
00164 
00165     // Go through and increment the numbers
00166     for (int i = 0; i < 10; i++) {
00167         printf("\rIncrementing numbers (%d/%d)... ", i, 10);
00168         fflush(stdout);
00169 
00170         // Get current stream position
00171         long pos = ftell(f);
00172 
00173         // Parse out the number and increment
00174         char buf[BUFFER_MAX_LEN];
00175         if (!fgets(buf, BUFFER_MAX_LEN, f)) {
00176             error("error: %s (%d)\n", strerror(errno), -errno);
00177         }
00178         char *endptr;
00179         int32_t number = strtol(buf, &endptr, 10);
00180         if (
00181             (errno == ERANGE) || // The number is too small/large
00182             (endptr == buf) ||   // No character was read
00183             (*endptr && *endptr != '\n') // The whole input was not converted
00184         ) {
00185             continue;
00186         }
00187         number += 1;
00188 
00189         // Seek to beginning of number
00190         fseek(f, pos, SEEK_SET);
00191     
00192         // Store number
00193         fprintf(f, "    %d\n", number);
00194 
00195         // Flush between write and read on same file
00196         fflush(f);
00197     }
00198     printf("\rIncrementing numbers (%d/%d)... OK\n", 10, 10);
00199 
00200     // Close the file which also flushes any cached writes
00201     printf("Closing \"/fs/numbers.txt\"... ");
00202     fflush(stdout);
00203     err = fclose(f);
00204     printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
00205     if (err < 0) {
00206         error("error: %s (%d)\n", strerror(errno), -errno);
00207     }
00208     
00209     // Display the root directory
00210     printf("Opening the root directory... ");
00211     fflush(stdout);
00212     DIR *d = opendir("/fs/");
00213     printf("%s\n", (!d ? "Fail :(" : "OK"));
00214     if (!d) {
00215         error("error: %s (%d)\n", strerror(errno), -errno);
00216     }
00217 
00218     printf("root directory:\n");
00219     while (true) {
00220         struct dirent *e = readdir(d);
00221         if (!e) {
00222             break;
00223         }
00224 
00225         printf("    %s\n", e->d_name);
00226     }
00227 
00228     printf("Closing the root directory... ");
00229     fflush(stdout);
00230     err = closedir(d);
00231     printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
00232     if (err < 0) {
00233         error("error: %s (%d)\n", strerror(errno), -errno);
00234     }
00235 
00236     // Display the numbers file
00237     printf("Opening \"/fs/numbers.txt\"... ");
00238     fflush(stdout);
00239     f = fopen("/fs/numbers.txt", "r");
00240     printf("%s\n", (!f ? "Fail :(" : "OK"));
00241     if (!f) {
00242         error("error: %s (%d)\n", strerror(errno), -errno);
00243     }
00244 
00245     printf("numbers:\n");
00246     while (!feof(f)) {
00247         int c = fgetc(f);
00248         printf("%c", c);
00249     }
00250 
00251     printf("\rClosing \"/fs/numbers.txt\"... ");
00252     fflush(stdout);
00253     err = fclose(f);
00254     printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
00255     if (err < 0) {
00256         error("error: %s (%d)\n", strerror(errno), -errno);
00257     }
00258 
00259     // Tidy up
00260     printf("Unmounting... ");
00261     fflush(stdout);
00262     err = fs.unmount();
00263     printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
00264     if (err < 0) {
00265         error("error: %s (%d)\n", strerror(-err), err);
00266     }
00267         
00268     printf("Mbed OS filesystem example done!\n");
00269 }
00270