From d84f5dab4d88f78fb2913ac6b9e1f0594fe5ffbf Mon Sep 17 00:00:00 2001 From: Carl Kugler Date: Sat, 11 Feb 2023 19:17:01 -0700 Subject: [PATCH] Clean up printfs --- .gitignore | 1 + .../PlatformIO/data_logger/platformio.ini | 15 +- examples/PlatformIO/data_logger/src/main.cpp | 28 +- examples/PlatformIO/hw_debug/.gitignore | 5 + examples/PlatformIO/hw_debug/platformio.ini | 22 + examples/PlatformIO/hw_debug/src/main.cpp | 104 ++ examples/PlatformIO/one_SDIO/platformio.ini | 13 +- examples/PlatformIO/one_SDIO/src/main.cpp | 50 +- examples/PlatformIO/one_SPI/platformio.ini | 11 +- examples/PlatformIO/one_SPI/src/main.cpp | 37 +- .../one_SPI_one_SDIO/platformio.ini | 13 +- .../PlatformIO/one_SPI_one_SDIO/src/main.cpp | 112 +- examples/command_line/CMakeLists.txt | 16 +- examples/command_line/main.cpp | 15 +- .../tests/CreateAndVerifyExampleFiles.c | 490 ------- .../tests/app4-IO_module_function_checker.c | 348 ----- examples/command_line/tests/bench.c | 311 ----- examples/command_line/tests/big_file_test.c | 182 --- .../tests/ff_stdio_tests_with_cwd.c | 1196 ----------------- examples/command_line/tests/simple.c | 154 --- examples/dynamic_config/CMakeLists.txt | 4 + examples/simple/CMakeLists.txt | 3 + include/FatFsSd.h | 26 +- library.json | 3 +- src/CMakeLists.txt | 2 +- src/ff15/documents/res/app4.c | 2 +- src/glue.c | 1 - src/include/my_debug.h | 16 +- src/include/util.h | 7 +- src/my_debug.c | 9 +- src/rtc.c | 1 - src/sd_driver/SDIO/rp2040_sdio.c | 16 +- src/sd_driver/SDIO/sd_card_sdio.c | 15 +- src/sd_driver/SPI/sd_spi.c | 1 - 34 files changed, 394 insertions(+), 2835 deletions(-) create mode 100644 examples/PlatformIO/hw_debug/.gitignore create mode 100644 examples/PlatformIO/hw_debug/platformio.ini create mode 100644 examples/PlatformIO/hw_debug/src/main.cpp delete mode 100644 examples/command_line/tests/CreateAndVerifyExampleFiles.c delete mode 100644 examples/command_line/tests/app4-IO_module_function_checker.c delete mode 100644 examples/command_line/tests/bench.c delete mode 100644 examples/command_line/tests/big_file_test.c delete mode 100644 examples/command_line/tests/ff_stdio_tests_with_cwd.c delete mode 100644 examples/command_line/tests/simple.c diff --git a/.gitignore b/.gitignore index b481a16..e5fe125 100755 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ *.png *.zip *.xlsx +*.bak **/.vscode diff --git a/examples/PlatformIO/data_logger/platformio.ini b/examples/PlatformIO/data_logger/platformio.ini index 6dbf2a9..8b05636 100644 --- a/examples/PlatformIO/data_logger/platformio.ini +++ b/examples/PlatformIO/data_logger/platformio.ini @@ -17,10 +17,13 @@ debug_tool = picoprobe upload_protocol = picoprobe monitor_port = COM4 monitor_speed = 115200 -build_flags = - -D PICO_STDIO_USB - -D PICO_STDIO_UART -lib_deps = +; build_flags = +; -D USE_PRINTF +; -D USE_DBG_PRINTF + +; lib_deps = ; https://github.com/carlk3/no-OS-FatFS-SD-SPI-RPi-Pico.git#sdio - carlk3/no-OS-FatFS-SD-SPI-RPi-Pico@^1.0.0 -lib_ldf_mode = chain+ + ; carlk3/no-OS-FatFS-SD-SPI-RPi-Pico@^1.0.0 +; Use local copy: +lib_deps = no-OS-FatFS-SD-SPI-RPi-Pico.dev_sdio +lib_extra_dirs = ../../../.. diff --git a/examples/PlatformIO/data_logger/src/main.cpp b/examples/PlatformIO/data_logger/src/main.cpp index 5670ba0..1acc2fd 100644 --- a/examples/PlatformIO/data_logger/src/main.cpp +++ b/examples/PlatformIO/data_logger/src/main.cpp @@ -12,6 +12,11 @@ CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +/* +This example reads analog input A0 and logs the voltage + in a file on an SD card once per second. +*/ + #include #include #include "FatFsSd.h" @@ -21,6 +26,7 @@ specific language governing permissions and limitations under the License. #include "pico/stdlib.h" /* Infrastructure*/ +#if USE_PRINTF extern "C" int printf(const char *__restrict format, ...) { char buf[256] = {0}; va_list xArgs; @@ -32,8 +38,26 @@ extern "C" int printf(const char *__restrict format, ...) { extern "C" int puts(const char *s) { return Serial1.println(s); } +#else +# define printf Serial1.printf +# define puts Serial1.println +#endif /* ********************************************************************** */ +/* +This example assumes the following wiring: + + | GPIO | Pico Pin | microSD | Function | + | ---- | -------- | ------- | ----------- | + | 16 | 21 | DET | Card Detect | + | 17 | 22 | CLK | SDIO_CLK | + | 18 | 24 | CMD | SDIO_CMD | + | 19 | 25 | DAT0 | SDIO_D0 | + | 20 | 26 | DAT1 | SDIO_D1 | + | 21 | 27 | DAT2 | SDIO_D2 | + | 22 | 29 | DAT3 | SDIO_D3 | + +*/ // Hardware Configuration of the SD Card "objects" static sd_card_t sd_cards[] = { // One for each SD card @@ -54,8 +78,8 @@ static sd_card_t sd_cards[] = { // One for each SD card .sdio_if = { .CMD_gpio = 18, .D0_gpio = 19, - .SDIO_PIO = pio1, - .DMA_IRQ_num = DMA_IRQ_1 + .SDIO_PIO = pio1, // Either pio0 or pio1 + .DMA_IRQ_num = DMA_IRQ_1 // Either DMA_IRQ_0 or DMA_IRQ_1 }, .use_card_detect = true, .card_detect_gpio = 16, // Card detect diff --git a/examples/PlatformIO/hw_debug/.gitignore b/examples/PlatformIO/hw_debug/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/examples/PlatformIO/hw_debug/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/examples/PlatformIO/hw_debug/platformio.ini b/examples/PlatformIO/hw_debug/platformio.ini new file mode 100644 index 0000000..adede6a --- /dev/null +++ b/examples/PlatformIO/hw_debug/platformio.ini @@ -0,0 +1,22 @@ +[env:pico] +platform = https://github.com/maxgerhardt/platform-raspberrypi.git +board = pico +framework = arduino +board_build.core = earlephilhower +debug_tool = picoprobe +upload_protocol = picoprobe +monitor_port = COM4 +monitor_speed = 115200 + +build_flags = + -D USE_PRINTF + -D USE_DBG_PRINTF + -I ../../tests + +; lib_deps = https://github.com/carlk3/no-OS-FatFS-SD-SPI-RPi-Pico.git#sdio +; Use local copy: +lib_deps = no-OS-FatFS-SD-SPI-RPi-Pico.dev_sdio +lib_extra_dirs = ../../../.. + +; evaluate C/C++ Preprocessor conditional syntax +; lib_ldf_mode = chain+ diff --git a/examples/PlatformIO/hw_debug/src/main.cpp b/examples/PlatformIO/hw_debug/src/main.cpp new file mode 100644 index 0000000..212e8f2 --- /dev/null +++ b/examples/PlatformIO/hw_debug/src/main.cpp @@ -0,0 +1,104 @@ +/* +Copyright 2023 Carl John Kugler III + +Licensed under the Apache License, Version 2.0 (the License); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +*/ + +/* +This example runs a low level I/O test than can be helpful for debugging hardware. +It will destroy the format of the SD card! +*/ +#include "FatFsSd.h" +#include "tests/tests.h" +// +#include "SerialUART.h" + +/* Infrastructure*/ +extern "C" int printf(const char *__restrict format, ...) { + char buf[256] = {0}; + va_list xArgs; + va_start(xArgs, format); + vsnprintf(buf, sizeof buf, format, xArgs); + va_end(xArgs); + return Serial1.printf("%s", buf); +} +extern "C" int puts(const char *s) { + return Serial1.println(s); +} + +/* ********************************************************************** */ +/* +This example assumes the following wiring: + + | GPIO | Pico Pin | microSD | Function | + | ---- | -------- | ------- | ----------- | + | 16 | 21 | DET | Card Detect | + | 17 | 22 | CLK | SDIO_CLK | + | 18 | 24 | CMD | SDIO_CMD | + | 19 | 25 | DAT0 | SDIO_D0 | + | 20 | 26 | DAT1 | SDIO_D1 | + | 21 | 27 | DAT2 | SDIO_D2 | + | 22 | 29 | DAT3 | SDIO_D3 | + +*/ +// Hardware Configuration of the SD Card "objects" +static sd_card_t sd_cards[] = { // One for each SD card + { + .pcName = "0:", // Name used to mount device + .type = SD_IF_SDIO, + /* + Pins CLK_gpio, D1_gpio, D2_gpio, and D3_gpio are at offsets from pin D0_gpio. + The offsets are determined by sd_driver\SDIO\rp2040_sdio.pio. + CLK_gpio = (D0_gpio + SDIO_CLK_PIN_D0_OFFSET) % 32; + As of this writing, SDIO_CLK_PIN_D0_OFFSET is 30, + which is -2 in mod32 arithmetic, so: + CLK_gpio = D0_gpio -2. + D1_gpio = D0_gpio + 1; + D2_gpio = D0_gpio + 2; + D3_gpio = D0_gpio + 3; + */ + .sdio_if = { + .CMD_gpio = 18, + .D0_gpio = 19, + .SDIO_PIO = pio1, + .DMA_IRQ_num = DMA_IRQ_1 + }, + .use_card_detect = true, + .card_detect_gpio = 16, // Card detect + .card_detected_true = 1 // What the GPIO read returns when a card is + // present. + } +}; +/* +The following *get_num, *get_by_num functions are required by the library API. +They are how the library finds out about the configuration. +*/ +extern "C" size_t sd_get_num() { return count_of(sd_cards); } +extern "C" sd_card_t *sd_get_by_num(size_t num) { + if (num <= sd_get_num()) { + return &sd_cards[num]; + } else { + return NULL; + } +} +// These need to be defined for the API even if SPI is not used: +extern "C" size_t spi_get_num() { return 0; } +extern "C" spi_t *spi_get_by_num(size_t num) { return NULL; } + +/* ********************************************************************** */ + +void setup() { + Serial1.begin(115200); // set up Serial library at 9600 bps + while (!Serial1) + ; // Serial is via USB; wait for enumeration + lliot(0); +} +void loop() {} \ No newline at end of file diff --git a/examples/PlatformIO/one_SDIO/platformio.ini b/examples/PlatformIO/one_SDIO/platformio.ini index 595ab8a..ed57b4d 100644 --- a/examples/PlatformIO/one_SDIO/platformio.ini +++ b/examples/PlatformIO/one_SDIO/platformio.ini @@ -8,13 +8,12 @@ upload_protocol = picoprobe monitor_port = COM4 monitor_speed = 115200 -build_flags = - -D PICO_STDIO_USB - -D PICO_STDIO_UART +; build_flags = -; lib_deps = no-OS-FatFS-SD-SPI-RPi-Pico.dev_sdio -; lib_extra_dirs = ../../../.. -lib_deps = https://github.com/carlk3/no-OS-FatFS-SD-SPI-RPi-Pico.git#sdio +; lib_deps = https://github.com/carlk3/no-OS-FatFS-SD-SPI-RPi-Pico.git#sdio +; Use local copy: +lib_deps = no-OS-FatFS-SD-SPI-RPi-Pico.dev_sdio +lib_extra_dirs = ../../../.. ; evaluate C/C++ Preprocessor conditional syntax -lib_ldf_mode = chain+ +; lib_ldf_mode = chain+ diff --git a/examples/PlatformIO/one_SDIO/src/main.cpp b/examples/PlatformIO/one_SDIO/src/main.cpp index 9c84e31..d4bad0e 100644 --- a/examples/PlatformIO/one_SDIO/src/main.cpp +++ b/examples/PlatformIO/one_SDIO/src/main.cpp @@ -12,25 +12,26 @@ CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +/* Write "Hello, world!\n" to SD Card */ #include "FatFsSd.h" // #include "SerialUART.h" -/* Infrastructure*/ -extern "C" int printf(const char *__restrict format, ...) { - char buf[256] = {0}; - va_list xArgs; - va_start(xArgs, format); - vsnprintf(buf, sizeof buf, format, xArgs); - va_end(xArgs); - return Serial1.printf("%s", buf); -} -extern "C" int puts(const char *s) { - return Serial1.println(s); -} - -/* ********************************************************************** */ +#define printf Serial1.printf +#define puts Serial1.println +/* +This example assumes the following wiring: + | GPIO | Pico Pin | microSD | Function | + | ---- | -------- | ------- | ----------- | + | 16 | 21 | DET | Card Detect | + | 17 | 22 | CLK | SDIO_CLK | + | 18 | 24 | CMD | SDIO_CMD | + | 19 | 25 | DAT0 | SDIO_D0 | + | 20 | 26 | DAT1 | SDIO_D1 | + | 21 | 27 | DAT2 | SDIO_D2 | + | 22 | 29 | DAT3 | SDIO_D3 | +*/ // Hardware Configuration of the SD Card "objects" static sd_card_t sd_cards[] = { // One for each SD card { @@ -59,6 +60,10 @@ static sd_card_t sd_cards[] = { // One for each SD card // present. } }; +/* +The following *get_num, *get_by_num functions are required by the library API. +They are how the library finds out about the configuration. +*/ extern "C" size_t sd_get_num() { return count_of(sd_cards); } extern "C" sd_card_t *sd_get_by_num(size_t num) { if (num <= sd_get_num()) { @@ -67,7 +72,7 @@ extern "C" sd_card_t *sd_get_by_num(size_t num) { return NULL; } } -// These need to be defined for the API: +// These need to be defined for the API even if SPI is not used: extern "C" size_t spi_get_num() { return 0; } extern "C" spi_t *spi_get_by_num(size_t num) { return NULL; } @@ -77,26 +82,31 @@ void setup() { Serial1.begin(115200); // set up Serial library at 9600 bps while (!Serial1) ; // Serial is via USB; wait for enumeration - time_init(); - puts("Hello, world!"); // See FatFs - Generic FAT Filesystem Module, "Application Interface", // http://elm-chan.org/fsw/ff/00index_e.html sd_card_t *pSD = sd_get_by_num(0); FRESULT fr = f_mount(&pSD->fatfs, pSD->pcName, 1); - if (FR_OK != fr) panic("f_mount error: %s (%d)\n", FRESULT_str(fr), fr); + if (FR_OK != fr) { + printf("f_mount error: %s (%d)\n", FRESULT_str(fr), fr); + for (;;) __BKPT(1); + } FIL fil; const char* const filename = "filename.txt"; fr = f_open(&fil, filename, FA_OPEN_APPEND | FA_WRITE); - if (FR_OK != fr && FR_EXIST != fr) - panic("f_open(%s) error: %s (%d)\n", filename, FRESULT_str(fr), fr); + if (FR_OK != fr && FR_EXIST != fr) { + printf("f_open(%s) error: %s (%d)\n", filename, FRESULT_str(fr), fr); + for (;;) __BKPT(2); + } if (f_printf(&fil, "Hello, world!\n") < 0) { printf("f_printf failed\n"); + for (;;) __BKPT(3); } fr = f_close(&fil); if (FR_OK != fr) { printf("f_close error: %s (%d)\n", FRESULT_str(fr), fr); + for (;;) __BKPT(4); } f_unmount(pSD->pcName); diff --git a/examples/PlatformIO/one_SPI/platformio.ini b/examples/PlatformIO/one_SPI/platformio.ini index 595ab8a..2fb880d 100644 --- a/examples/PlatformIO/one_SPI/platformio.ini +++ b/examples/PlatformIO/one_SPI/platformio.ini @@ -9,12 +9,11 @@ monitor_port = COM4 monitor_speed = 115200 build_flags = - -D PICO_STDIO_USB - -D PICO_STDIO_UART -; lib_deps = no-OS-FatFS-SD-SPI-RPi-Pico.dev_sdio -; lib_extra_dirs = ../../../.. -lib_deps = https://github.com/carlk3/no-OS-FatFS-SD-SPI-RPi-Pico.git#sdio +; lib_deps = https://github.com/carlk3/no-OS-FatFS-SD-SPI-RPi-Pico.git#sdio +; Use local copy: +lib_deps = no-OS-FatFS-SD-SPI-RPi-Pico.dev_sdio +lib_extra_dirs = ../../../.. ; evaluate C/C++ Preprocessor conditional syntax -lib_ldf_mode = chain+ +; lib_ldf_mode = chain+ diff --git a/examples/PlatformIO/one_SPI/src/main.cpp b/examples/PlatformIO/one_SPI/src/main.cpp index 794ae48..da472b8 100644 --- a/examples/PlatformIO/one_SPI/src/main.cpp +++ b/examples/PlatformIO/one_SPI/src/main.cpp @@ -16,21 +16,21 @@ specific language governing permissions and limitations under the License. // #include "SerialUART.h" -/* Infrastructure*/ -extern "C" int printf(const char *__restrict format, ...) { - char buf[256] = {0}; - va_list xArgs; - va_start(xArgs, format); - vsnprintf(buf, sizeof buf, format, xArgs); - va_end(xArgs); - return Serial1.printf("%s", buf); -} -extern "C" int puts(const char *s) { - return Serial1.println(s); -} +#define printf Serial1.printf +#define puts Serial1.println /* ********************************************************************** */ +/* This example assumes the following wiring: + | signal | SPI1 | GPIO | card | Description | + | ------ | ---- | ---- | ---- | ---------------------- | + | MISO | RX | 12 | DO | Master In, Slave Out | + | CS0 | CSn | 09 | CS | Slave (or Chip) Select | + | SCK | SCK | 14 | SCLK | SPI clock | + | MOSI | TX | 15 | DI | Master Out, Slave In | + | CD | | 13 | DET | Card Detect | +*/ + // Hardware Configuration of SPI "objects" // Note: multiple SD cards can be driven by one SPI if they use different slave // selects. @@ -90,18 +90,25 @@ void setup() { // http://elm-chan.org/fsw/ff/00index_e.html sd_card_t *pSD = sd_get_by_num(0); FRESULT fr = f_mount(&pSD->fatfs, pSD->pcName, 1); - if (FR_OK != fr) panic("f_mount error: %s (%d)\n", FRESULT_str(fr), fr); + if (FR_OK != fr) { + printf("f_mount error: %s (%d)\n", FRESULT_str(fr), fr); + for (;;) __BKPT(1); + } FIL fil; const char* const filename = "filename.txt"; fr = f_open(&fil, filename, FA_OPEN_APPEND | FA_WRITE); - if (FR_OK != fr && FR_EXIST != fr) - panic("f_open(%s) error: %s (%d)\n", filename, FRESULT_str(fr), fr); + if (FR_OK != fr && FR_EXIST != fr) { + printf("f_open(%s) error: %s (%d)\n", filename, FRESULT_str(fr), fr); + for (;;) __BKPT(2); + } if (f_printf(&fil, "Hello, world!\n") < 0) { printf("f_printf failed\n"); + for (;;) __BKPT(3); } fr = f_close(&fil); if (FR_OK != fr) { printf("f_close error: %s (%d)\n", FRESULT_str(fr), fr); + for (;;) __BKPT(4); } f_unmount(pSD->pcName); diff --git a/examples/PlatformIO/one_SPI_one_SDIO/platformio.ini b/examples/PlatformIO/one_SPI_one_SDIO/platformio.ini index 595ab8a..ed57b4d 100644 --- a/examples/PlatformIO/one_SPI_one_SDIO/platformio.ini +++ b/examples/PlatformIO/one_SPI_one_SDIO/platformio.ini @@ -8,13 +8,12 @@ upload_protocol = picoprobe monitor_port = COM4 monitor_speed = 115200 -build_flags = - -D PICO_STDIO_USB - -D PICO_STDIO_UART +; build_flags = -; lib_deps = no-OS-FatFS-SD-SPI-RPi-Pico.dev_sdio -; lib_extra_dirs = ../../../.. -lib_deps = https://github.com/carlk3/no-OS-FatFS-SD-SPI-RPi-Pico.git#sdio +; lib_deps = https://github.com/carlk3/no-OS-FatFS-SD-SPI-RPi-Pico.git#sdio +; Use local copy: +lib_deps = no-OS-FatFS-SD-SPI-RPi-Pico.dev_sdio +lib_extra_dirs = ../../../.. ; evaluate C/C++ Preprocessor conditional syntax -lib_ldf_mode = chain+ +; lib_ldf_mode = chain+ diff --git a/examples/PlatformIO/one_SPI_one_SDIO/src/main.cpp b/examples/PlatformIO/one_SPI_one_SDIO/src/main.cpp index f005eab..5e1cfea 100644 --- a/examples/PlatformIO/one_SPI_one_SDIO/src/main.cpp +++ b/examples/PlatformIO/one_SPI_one_SDIO/src/main.cpp @@ -1,87 +1,109 @@ -/* +/* Copyright 2023 Carl John Kugler III -Licensed under the Apache License, Version 2.0 (the License); you may not use -this file except in compliance with the License. You may obtain a copy of the +Licensed under the Apache License, Version 2.0 (the License); you may not use +this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software distributed -under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR -CONDITIONS OF ANY KIND, either express or implied. See the License for the + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include + #include "FatFsSd.h" #include "SerialUART.h" +#define printf Serial1.printf +#define puts Serial1.println + static const uint led_pin = PICO_DEFAULT_LED_PIN; static std::vector spis; static std::vector sd_cards; -/* Infrastructure*/ -extern "C" { - int printf(const char *__restrict format, ...) { - char buf[256] = {0}; - va_list xArgs; - va_start(xArgs, format); - vsnprintf(buf, sizeof buf, format, xArgs); - va_end(xArgs); - return Serial1.printf("%s", buf); - } - int puts (const char *s) { - return Serial1.println(s); - } -} - /* ********************************************************************** */ extern "C" size_t sd_get_num() { return sd_cards.size(); } extern "C" sd_card_t *sd_get_by_num(size_t num) { - if (num <= sd_get_num()) { - return sd_cards[num]; - } else { - return NULL; - } + if (num <= sd_get_num()) { + return sd_cards[num]; + } else { + return NULL; + } } extern "C" size_t spi_get_num() { return spis.size(); } extern "C" spi_t *spi_get_by_num(size_t num) { - if (num <= sd_get_num()) { - return spis[num]; - } else { - return NULL; - } + if (num <= sd_get_num()) { + return spis[num]; + } else { + return NULL; + } } void add_spi(spi_t *spi) { spis.push_back(spi); } void add_sd_card(sd_card_t *sd_card) { sd_cards.push_back(sd_card); } void test(sd_card_t *pSD) { + // See FatFs - Generic FAT Filesystem Module, "Application Interface", // http://elm-chan.org/fsw/ff/00index_e.html FRESULT fr = f_mount(&pSD->fatfs, pSD->pcName, 1); - if (FR_OK != fr) panic("f_mount error: %s (%d)\n", FRESULT_str(fr), fr); + if (FR_OK != fr) { + printf("f_mount error: %s (%d)\n", FRESULT_str(fr), fr); + for (;;) __BKPT(1); + } fr = f_chdrive(pSD->pcName); - if (FR_OK != fr) panic("f_chdrive error: %s (%d)\n", FRESULT_str(fr), fr); + if (FR_OK != fr) { + printf("f_chdrive error: %s (%d)\n", FRESULT_str(fr), fr); + for (;;) __BKPT(2); + } FIL fil; const char *const filename = "filename.txt"; fr = f_open(&fil, filename, FA_OPEN_APPEND | FA_WRITE); - if (FR_OK != fr && FR_EXIST != fr) - panic("f_open(%s) error: %s (%d)\n", filename, FRESULT_str(fr), fr); + if (FR_OK != fr && FR_EXIST != fr) { + printf("f_open(%s) error: %s (%d)\n", filename, FRESULT_str(fr), fr); + for (;;) __BKPT(3); + } if (f_printf(&fil, "Hello, world!\n") < 0) { printf("f_printf failed\n"); + for (;;) __BKPT(4); } fr = f_close(&fil); if (FR_OK != fr) { printf("f_close error: %s (%d)\n", FRESULT_str(fr), fr); + for (;;) __BKPT(5); } - f_unmount(pSD->pcName); } /* ********************************************************************** */ +/* +This example assumes the following wiring for SD card 0: + + | signal | SPI1 | GPIO | card | Description | + | ------ | ---- | ---- | ---- | ---------------------- | + | MISO | RX | 12 | DO | Master In, Slave Out | + | CS0 | CSn | 09 | CS | Slave (or Chip) Select | + | SCK | SCK | 14 | SCLK | SPI clock | + | MOSI | TX | 15 | DI | Master Out, Slave In | + | CD | | 13 | DET | Card Detect | + +This example assumes the following wiring for SD card 1: + + | GPIO | card | Function | + | ---- | ---- | ----------- | + | 16 | DET | Card Detect | + | 17 | CLK | SDIO_CLK | + | 18 | CMD | SDIO_CMD | + | 19 | DAT0 | SDIO_D0 | + | 20 | DAT1 | SDIO_D1 | + | 21 | DAT2 | SDIO_D2 | + | 22 | DAT3 | SDIO_D3 | +*/ void setup() { Serial1.begin(115200); // set up Serial library at 9600 bps @@ -99,7 +121,11 @@ void setup() { // Hardware Configuration of SPI "object" spi_t *p_spi = new spi_t; memset(p_spi, 0, sizeof(spi_t)); - if (!p_spi) panic("Out of memory"); + if (!p_spi) { + printf("Out of memory"); + for (;;) __BKPT(3); + } + p_spi->hw_inst = spi1; // SPI component p_spi->miso_gpio = 12; // GPIO number (not pin number) p_spi->mosi_gpio = 15; @@ -109,7 +135,10 @@ void setup() { // Hardware Configuration of the SD Card "object" sd_card_t *p_sd_card = new sd_card_t; - if (!p_sd_card) panic("Out of memory"); + if (!p_sd_card) { + printf("Out of memory"); + for (;;) __BKPT(6); + } memset(p_sd_card, 0, sizeof(sd_card_t)); p_sd_card->pcName = "0:"; // Name used to mount device p_sd_card->type = SD_IF_SPI, @@ -123,7 +152,10 @@ void setup() { /* Add another SD card */ p_sd_card = new sd_card_t; - if (!p_sd_card) panic("Out of memory"); + if (!p_sd_card) { + printf("Out of memory"); + for (;;) __BKPT(7); + } memset(p_sd_card, 0, sizeof(sd_card_t)); p_sd_card->pcName = "1:"; // Name used to mount device p_sd_card->type = SD_IF_SDIO; diff --git a/examples/command_line/CMakeLists.txt b/examples/command_line/CMakeLists.txt index a761846..1bdbfb0 100644 --- a/examples/command_line/CMakeLists.txt +++ b/examples/command_line/CMakeLists.txt @@ -20,12 +20,12 @@ add_executable(command_line main.cpp hw_config.c data_log_demo.c - tests/bench.c - tests/simple.c - tests/app4-IO_module_function_checker.c - tests/big_file_test.c - tests/CreateAndVerifyExampleFiles.c - tests/ff_stdio_tests_with_cwd.c + ../../src/tests/bench.c + ../../src/tests/simple.c + ../../src/tests/app4-IO_module_function_checker.c + ../../src/tests/big_file_test.c + ../../src/tests/CreateAndVerifyExampleFiles.c + ../../src/tests/ff_stdio_tests_with_cwd.c ) # Add the standard library to the build target_link_libraries(command_line pico_stdlib) @@ -33,6 +33,10 @@ target_link_libraries(command_line pico_stdlib) # target_compile_options(command_line PUBLIC -Wall -Wextra -Wno-unused-function -Wno-unused-parameter) target_compile_options(command_line PUBLIC -Wall -Wextra -Wno-unused-parameter) +# This program is useless without standard standard input and output. +# add_compile_definitions(USE_PRINTF USE_DBG_PRINTF) +add_compile_definitions(USE_PRINTF) + set_property(TARGET command_line APPEND_STRING PROPERTY LINK_FLAGS "-Wl,--print-memory-usage") pico_set_program_name(command_line "command_line") diff --git a/examples/command_line/main.cpp b/examples/command_line/main.cpp index e1682ee..b1e8f2c 100644 --- a/examples/command_line/main.cpp +++ b/examples/command_line/main.cpp @@ -18,19 +18,12 @@ #include "my_debug.h" #include "rtc.h" #include "sd_card.h" +#include "tests.h" // #include "util.h" // for wiring test -extern "C" { - int lliot(size_t pnum); - void ls(const char *dir); - void simple(); - void bench(char const* logdrv); - void big_file_test(const char *const pathname, size_t size, - uint32_t seed); - void vCreateAndVerifyExampleFiles(const char *pcMountPath); - void vStdioWithCWDTest(const char *pcMountPath); - bool process_logger(); -} +#ifndef USE_PRINTF +#error This program is useless without standard input and output. +#endif static bool logger_enabled; static const uint32_t period = 1000; diff --git a/examples/command_line/tests/CreateAndVerifyExampleFiles.c b/examples/command_line/tests/CreateAndVerifyExampleFiles.c deleted file mode 100644 index 09e8286..0000000 --- a/examples/command_line/tests/CreateAndVerifyExampleFiles.c +++ /dev/null @@ -1,490 +0,0 @@ -/* CreateAndVerifyExampleFiles.c -Copyright 2021 Carl John Kugler III - -Licensed under the Apache License, Version 2.0 (the License); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at - - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software distributed -under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR -CONDITIONS OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. -*/ -/* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. - All rights reserved - - VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. - - *************************************************************************** - >>! NOTE: The modification to the GPL is included to allow you to !<< - >>! distribute a combined work that includes FreeRTOS without being !<< - >>! obliged to provide the source code for proprietary components !<< - >>! outside of the FreeRTOS kernel. !<< - *************************************************************************** - - FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. Full license text is available on the following - link: http://www.freertos.org/a00114.html - - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that is more than just the market leader, it * - * is the industry's de facto standard. * - * * - * Help yourself get started quickly while simultaneously helping * - * to support the FreeRTOS project by purchasing a FreeRTOS * - * tutorial book, reference manual, or both: * - * http://www.FreeRTOS.org/Documentation * - * * - *************************************************************************** - - http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading - the FAQ page "My application does not run, what could be wrong?". Have you - defined configASSERT()? - - http://www.FreeRTOS.org/support - In return for receiving this top quality - embedded software for free we request you assist our global community by - participating in the support forum. - - http://www.FreeRTOS.org/training - Investing in training allows your team to - be as productive as possible as early as possible. Now you can receive - FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers - Ltd, and the world's leading authority on the world's leading RTOS. - - http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, - including FreeRTOS+Trace - an indispensable productivity tool, a DOS - compatible FAT file system, and our tiny thread aware UDP/IP stack. - - http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. - Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. - - http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High - Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and commercial middleware. - - http://www.SafeRTOS.com - High Integrity Systems also provide a safety - engineered and independently SIL3 certified version for use in safety and - mission critical applications that require provable dependability. - - 1 tab == 4 spaces! -*/ - - -/* - * Create and verify a few example files using both line based and character - * based reads and writes. - */ - -/* FreeRTOS+FAT headers. */ -//#include "ff_headers.h" -#include "ff_stdio.h" - -#include - -//#define TRACE_PRINTF(fmt, args...) -#define TRACE_PRINTF printf - -/* The number of bytes read/written to the example files at a time. */ -#define fsRAM_BUFFER_SIZE 200 - -/* The number of bytes written to the file that uses f_putc() and f_getc(). */ -#define fsPUTC_FILE_SIZE 100 - -/* - * Create a set of example files in the root directory of the volume using - * ff_fwrite(). - */ -static void prvCreateDemoFilesUsing_ff_fwrite( const char *pcMountPath ); - -/* - * Use ff_fread() to read back and verify the files that were created by - * prvCreateDemoFilesUsing_ff_fwrite(). - */ -static void prvVerifyDemoFileUsing_ff_fread( void ); - -/* - * Create an example file in a sub-directory using f_putc(). - */ -static void prvCreateDemoFileUsing_ff_fputc( const char *pcMountPath ); - -/* - * Use f_getc() to read back and verify the file that was created by - * prvCreateDemoFileUsing_f_putc(). - */ -static void prvVerifyDemoFileUsing_ff_fgetc( const char *pcMountPath ); - -/* - * Create the configHTTP_ROOT directory, and add a basic default web page. - */ -#if( ipconfigUSE_HTTP == 1 ) - - #ifndef configHTTP_ROOT - #error configHTTP_ROOT must be defined to a string that holds the directory to be used as the root for the HTTP server - #endif - - static void prvCreateDefaultWebPage( void ); - -#endif /* ipconfigUSE_HTTP */ - -/* Names of directories that are created. */ -static const char *pcDirectory1 = "SUB1", *pcDirectory2 = "SUB2", *pcFullPath = "/SUB1/SUB2"; - -/*-----------------------------------------------------------*/ - -void vCreateAndVerifyExampleFiles( const char *pcMountPath ) -{ - TRACE_PRINTF("%s(pcMountPath=%s)\n", __FUNCTION__, pcMountPath); - - // Pretend mount path: - int lResult = ff_mkdir(pcMountPath); - if (-1 == lResult && errno != EEXIST) { - printf("ff_mkdir %s failed: %s (%d)\n", pcMountPath, - strerror(errno), errno); - return; - } - - /* Create and verify a few example files using both line based and character - based reads and writes. */ - prvCreateDemoFilesUsing_ff_fwrite( pcMountPath ); - // vTaskDelay(rand() % 5); - prvVerifyDemoFileUsing_ff_fread(); - // vTaskDelay(rand() % 5); - prvCreateDemoFileUsing_ff_fputc( pcMountPath ); - // vTaskDelay(rand() % 5); - prvVerifyDemoFileUsing_ff_fgetc( pcMountPath ); - // vTaskDelay(rand() % 5); - - #if( ipconfigUSE_HTTP == 1 ) - { - prvCreateDefaultWebPage(); - } - #endif /* ipconfigUSE_HTTP */ -} -/*-----------------------------------------------------------*/ - -static void prvCreateDemoFilesUsing_ff_fwrite( const char *pcMountPath ) -{ - TRACE_PRINTF("%s(pcMountPath=%s)\n", __FUNCTION__, pcMountPath); -BaseType_t xFileNumber, xWriteNumber; -const BaseType_t xMaxFiles = 5; -int32_t lItemsWritten; -int32_t lResult; -FF_FILE *pxFile; -char *pcRAMBuffer, *pcFileName; - - /* Allocate buffers used to hold date written to/from the disk, and the - file names. */ - pcRAMBuffer = ( char * ) pvPortMalloc( fsRAM_BUFFER_SIZE ); - pcFileName = ( char * ) pvPortMalloc( ffconfigMAX_FILENAME ); - configASSERT( pcRAMBuffer ); - configASSERT( pcFileName ); - - /* Ensure in the root of the mount being used. */ - lResult = ff_chdir( pcMountPath ); - configASSERT( lResult >= 0 ); - - /* Create xMaxFiles files. Each created file will be - ( xFileNumber * fsRAM_BUFFER_SIZE ) bytes in length, and filled - with a different repeating character. */ - for( xFileNumber = 1; xFileNumber <= xMaxFiles; xFileNumber++ ) - { - /* Generate a file name. */ - snprintf( pcFileName, ffconfigMAX_FILENAME, "root%03d.txt", ( int ) xFileNumber ); - - /* Obtain the current working directory and print out the file name and - the directory into which the file is being written. */ - ff_getcwd( pcRAMBuffer, fsRAM_BUFFER_SIZE ); - FF_PRINTF( "Creating file %s in %s\r\n", pcFileName, pcRAMBuffer ); - - /* Open the file, creating the file if it does not already exist. */ - pxFile = ff_fopen( pcFileName, "w" ); - configASSERT( pxFile ); - - /* Fill the RAM buffer with data that will be written to the file. This - is just a repeating ascii character that indicates the file number. */ - memset( pcRAMBuffer, ( int ) ( '0' + xFileNumber ), fsRAM_BUFFER_SIZE ); - - /* Write the RAM buffer to the opened file a number of times. The - number of times the RAM buffer is written to the file depends on the - file number, so the length of each created file will be different. */ - for( xWriteNumber = 0; xWriteNumber < xFileNumber; xWriteNumber++ ) - { - lItemsWritten = ff_fwrite( pcRAMBuffer, fsRAM_BUFFER_SIZE, 1, pxFile ); - configASSERT( lItemsWritten == 1 ); - } - - /* Close the file so another file can be created. */ - ff_fclose( pxFile ); - } - - vPortFree( pcRAMBuffer ); - vPortFree( pcFileName ); -} -/*-----------------------------------------------------------*/ - -static void prvVerifyDemoFileUsing_ff_fread( void ) -{ - TRACE_PRINTF("%s()\n", __FUNCTION__); -BaseType_t xFileNumber, xReadNumber; -const BaseType_t xMaxFiles = 5; -size_t xItemsRead, xChar; -FF_FILE *pxFile; -char *pcRAMBuffer, *pcFileName; - - /* Allocate buffers used to hold date written to/from the disk, and the - file names. */ - pcRAMBuffer = ( char * ) pvPortMalloc( fsRAM_BUFFER_SIZE ); - pcFileName = ( char * ) pvPortMalloc( ffconfigMAX_FILENAME ); - configASSERT( pcRAMBuffer ); - configASSERT( pcFileName ); - - /* Read back the files that were created by - prvCreateDemoFilesUsing_ff_fwrite(). */ - for( xFileNumber = 1; xFileNumber <= xMaxFiles; xFileNumber++ ) - { - /* Generate the file name. */ - snprintf( pcFileName, ffconfigMAX_FILENAME, "root%03d.txt", ( int ) xFileNumber ); - - /* Obtain the current working directory and print out the file name and - the directory from which the file is being read. */ - ff_getcwd( pcRAMBuffer, fsRAM_BUFFER_SIZE ); - FF_PRINTF( "Reading file %s from %s\r\n", pcFileName, pcRAMBuffer ); - - /* Open the file for reading. */ - pxFile = ff_fopen( pcFileName, "r" ); - FF_PRINTF("FF_fopen(%s): %s (%d)\r\r\n", pcFileName, strerror(errno), errno); - - configASSERT( pxFile ); - - /* Read the file into the RAM buffer, checking the file contents are as - expected. The size of the file depends on the file number. */ - for( xReadNumber = 0; xReadNumber < xFileNumber; xReadNumber++ ) - { - /* Start with the RAM buffer clear. */ - memset( pcRAMBuffer, 0x00, fsRAM_BUFFER_SIZE ); - - xItemsRead = ff_fread( pcRAMBuffer, fsRAM_BUFFER_SIZE, 1, pxFile ); - configASSERT( xItemsRead == 1 ); - - /* Check the RAM buffer is filled with the expected data. Each - file contains a different repeating ascii character that indicates - the number of the file. */ - for( xChar = 0; xChar < fsRAM_BUFFER_SIZE; xChar++ ) - { - configASSERT( pcRAMBuffer[ xChar ] == ( '0' + ( char ) xFileNumber ) ); - } - } - - /* Close the file. */ - ff_fclose( pxFile ); - } - - vPortFree( pcRAMBuffer ); - vPortFree( pcFileName ); - - /*_RB_ also test what happens when attempting to read using too large item - sizes, etc. */ -} -/*-----------------------------------------------------------*/ - -static void prvCreateDemoFileUsing_ff_fputc( const char *pcMountPath ) -{ - TRACE_PRINTF("%s(pcMountPath=%s)\n", __FUNCTION__, pcMountPath); -int32_t iReturn, iByte, iReturned; -FF_FILE *pxFile; -char *pcRAMBuffer, *pcFileName; - - /* Allocate buffers used to hold date written to/from the disk, and the - file names. */ - pcRAMBuffer = ( char * ) pvPortMalloc( fsRAM_BUFFER_SIZE ); - pcFileName = ( char * ) pvPortMalloc( ffconfigMAX_FILENAME ); - configASSERT( pcRAMBuffer ); - configASSERT( pcFileName ); - - /* Obtain and print out the working directory. */ - ff_getcwd( pcRAMBuffer, fsRAM_BUFFER_SIZE ); - FF_PRINTF( "In directory %s\r\n", pcRAMBuffer ); - - /* Create a sub directory. */ - iReturn = ff_mkdir( pcDirectory1 ); - configASSERT( iReturn == pdFREERTOS_ERRNO_NONE ); - - /* Move into the created sub-directory. */ - iReturn = ff_chdir( pcDirectory1 ); - if (iReturn != pdFREERTOS_ERRNO_NONE) { - FF_PRINTF("ff_chdir error: %s (%d)\n", strerror(errno), errno); - configASSERT( iReturn == pdFREERTOS_ERRNO_NONE ); - } - /* Obtain and print out the working directory. */ - ff_getcwd( pcRAMBuffer, fsRAM_BUFFER_SIZE ); - FF_PRINTF( "In directory %s\r\n", pcRAMBuffer ); - - /* Create a subdirectory in the new directory. */ - iReturn = ff_mkdir( pcDirectory2 ); - configASSERT( iReturn == pdFREERTOS_ERRNO_NONE ); - - /* Move into the directory just created - now two directories down from - the root. */ - iReturn = ff_chdir( pcDirectory2 ); - configASSERT( iReturn == pdFREERTOS_ERRNO_NONE ); - - /* Obtain and print out the working directory. */ - ff_getcwd( pcRAMBuffer, fsRAM_BUFFER_SIZE ); - FF_PRINTF( "In directory %s\r\n", pcRAMBuffer ); - snprintf( pcFileName, ffconfigMAX_FILENAME, "%s%s", pcMountPath, pcFullPath ); - if (0 != strcmp( pcRAMBuffer, pcFileName )) { - FF_PRINTF( "pcRAMBuffer:%s,pcFileName:%s\n", pcRAMBuffer, pcFileName); - configASSERT( strcmp( pcRAMBuffer, pcFileName ) == 0 ); - } - - /* Generate the file name. */ - snprintf( pcFileName, ffconfigMAX_FILENAME, "%s.txt", pcDirectory2 ); - - /* Print out the file name and the directory into which the file is being - written. */ - FF_PRINTF( "Writing file %s in %s\r\n", pcFileName, pcRAMBuffer ); - - pxFile = ff_fopen( pcFileName, "w" ); - configASSERT( pxFile ); - - /* Create a file 1 byte at a time. The file is filled with incrementing - ascii characters starting from '0'. */ - for( iByte = 0; iByte < fsPUTC_FILE_SIZE; iByte++ ) - { - iReturned = ff_fputc( ( ( int ) '0' + iByte ), pxFile ); - configASSERT( iReturned == ( ( int ) '0' + iByte ) ); - } - - /* Finished so close the file. */ - ff_fclose( pxFile ); - - /* Move back to the root directory. */ - iReturned = ff_chdir( "../.." ); - configASSERT( iReturn == pdFREERTOS_ERRNO_NONE ); - - /* Obtain and print out the working directory. */ - ff_getcwd( pcRAMBuffer, fsRAM_BUFFER_SIZE ); - FF_PRINTF( "Back in root directory %s\r\n", pcRAMBuffer ); - configASSERT( strcmp( pcRAMBuffer, pcMountPath ) == 0 ); - - vPortFree( pcRAMBuffer ); - vPortFree( pcFileName ); -} -/*-----------------------------------------------------------*/ - -static void prvVerifyDemoFileUsing_ff_fgetc( const char *pcMountPath ) -{ - TRACE_PRINTF("%s(pcMountPath=%s)\n", __FUNCTION__, pcMountPath); -int iByte, iReturned; -FF_FILE *pxFile; -char *pcRAMBuffer, *pcFileName; - - /* Allocate buffers used to hold date written to/from the disk, and the - file names. */ - pcRAMBuffer = ( char * ) pvPortMalloc( fsRAM_BUFFER_SIZE ); - pcFileName = ( char * ) pvPortMalloc( ffconfigMAX_FILENAME ); - configASSERT( pcRAMBuffer ); - configASSERT( pcFileName ); - - /* Move into the directory in which the file was created. */ - snprintf( pcFileName, ffconfigMAX_FILENAME, "%s%s", pcMountPath, pcFullPath ); - iReturned = ff_chdir( pcFileName ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - /* Obtain and print out the working directory. */ - ff_getcwd( pcRAMBuffer, fsRAM_BUFFER_SIZE ); - FF_PRINTF( "Back in directory %s\r\n", pcRAMBuffer ); - configASSERT( strcmp( pcRAMBuffer, pcFileName ) == 0 ); - - /* pcFileName is about to be overwritten - take a copy. */ - strcpy( pcRAMBuffer, pcFileName ); - - /* Generate the file name. */ - sprintf( pcFileName, "%s.txt", pcDirectory2 ); - - /* Print out the file name and the directory from which the file is being - read. */ - FF_PRINTF( "Reading file %s in %s\r\n", pcFileName, pcRAMBuffer ); - - /* This time the file is opened for reading. */ - pxFile = ff_fopen( pcFileName, "r" ); - - /* Read the file 1 byte at a time. */ - for( iByte = 0; iByte < fsPUTC_FILE_SIZE; iByte++ ) - { - iReturned = ff_fgetc( pxFile ); - if (iReturned != ( ( int ) '0' + iByte )) { - TRACE_PRINTF("iReturned=%d, ( ( int ) '0' + iByte ))=%d\n", iReturned, ( ( int ) '0' + iByte )); - } - configASSERT( iReturned == ( ( int ) '0' + iByte ) ); - } - - /* Should not be able to read another bytes. */ - iReturned = ff_fgetc( pxFile ); - configASSERT( iReturned == FF_EOF ); - - /* Finished so close the file. */ - ff_fclose( pxFile ); - - /* Move back to the root directory. */ - iReturned = ff_chdir( "../.." ); - - /* Obtain and print out the working directory. */ - ff_getcwd( pcRAMBuffer, fsRAM_BUFFER_SIZE ); - FF_PRINTF( "Back in root directory %s\r\n", pcRAMBuffer ); - - vPortFree( pcRAMBuffer ); - vPortFree( pcFileName ); -} -/*-----------------------------------------------------------*/ - -#if( ipconfigUSE_HTTP == 1 ) - - static void prvCreateDefaultWebPage( void ) - { - int iReturned; - size_t x; - FF_FILE *pxFile; - - /* Create the directory used as the root of the HTTP server. */ - iReturned = ff_mkdir( configHTTP_ROOT ); - - if( iReturned == pdFREERTOS_ERRNO_NONE ) - { - /* Move into the configHTTP_ROOT directory. */ - ff_chdir( configHTTP_ROOT ); - - /* Create each file defined by the xHTTPFilesToCopy array, which is - defined in DefaultWebPages.h. */ - for( x = 0; x < sizeof( xHTTPFilesToCopy ) / sizeof( xFileToCopy_t ); x++ ) - { - /* Create the file. */ - pxFile = ff_fopen( xHTTPFilesToCopy[ x ].pcFileName, "w+" ); - - if( pxFile != NULL ) - { - /* Write out all the data to the file. */ - ff_fwrite( xHTTPFilesToCopy[ x ].pucFileData, - xHTTPFilesToCopy[ x ].xFileSize, - 1, - pxFile ); - - ff_fclose( pxFile ); - } - } - } - } - -#endif /* ipconfigUSE_HTTP */ -/*-----------------------------------------------------------*/ diff --git a/examples/command_line/tests/app4-IO_module_function_checker.c b/examples/command_line/tests/app4-IO_module_function_checker.c deleted file mode 100644 index 9869ce7..0000000 --- a/examples/command_line/tests/app4-IO_module_function_checker.c +++ /dev/null @@ -1,348 +0,0 @@ -/*----------------------------------------------------------------------/ -/ Low level disk I/O module function checker / -/-----------------------------------------------------------------------/ -/ WARNING: The data on the target drive will be lost! -*/ -/* app4-IO_module_function_checker.c -Originally from [Compatibility Checker for Storage Device Control Module](http://elm-chan.org/fsw/ff/res/app4.c). -*/ -/*----------------------------------------------------------------------------/ -/ FatFs - Generic FAT Filesystem Module Rx.xx / -/-----------------------------------------------------------------------------/ -/ -/ Copyright (C) 20xx, ChaN, all right reserved. -/ -/ FatFs module is an open source software. Redistribution and use of FatFs in -/ source and binary forms, with or without modification, are permitted provided -/ that the following condition is met: -/ -/ 1. Redistributions of source code must retain the above copyright notice, -/ this condition and the following disclaimer. -/ -/ This software is provided by the copyright holder and contributors "AS IS" -/ and any warranties related to this software are DISCLAIMED. -/ The copyright owner or contributors be NOT LIABLE for any damages caused -/ by use of this software. -/----------------------------------------------------------------------------*/ -/* -Modifications: Copyright 2021 Carl John Kugler III - -Licensed under the Apache License, Version 2.0 (the License); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at - - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software distributed -under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR -CONDITIONS OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. -*/ - -#include -#include -#include "ff.h" /* Declarations of sector size */ -#include "diskio.h" /* Declarations of disk functions */ - -#include "hardware/gpio.h" // gpio_put - -static DWORD pn ( /* Pseudo random number generator */ - DWORD pns /* !0:Initialize, 0:Read */ -) -{ - static DWORD lfsr; - UINT n; - - - if (pns) { - lfsr = pns; - for (n = 0; n < 32; n++) pn(0); - } - if (lfsr & 1) { - lfsr >>= 1; - lfsr ^= 0x80200003; - } else { - lfsr >>= 1; - } - return lfsr; -} - - -int test_diskio ( - BYTE pdrv, /* Physical drive number to be checked (all data on the drive will be lost) */ - UINT ncyc, /* Number of test cycles */ - DWORD* buff, /* Pointer to the working buffer */ - UINT sz_buff /* Size of the working buffer in unit of byte */ -) -{ - UINT n, cc, ns; - DWORD sz_drv, lba, lba2, sz_eblk, pns = 1; - WORD sz_sect; - BYTE *pbuff = (BYTE*)buff; - DSTATUS ds; - DRESULT dr; - - printf("test_diskio(%u, %u, 0x%08X, 0x%08X)\n", pdrv, ncyc, (UINT)buff, sz_buff); - - if (sz_buff < FF_MAX_SS + 8) { - printf("Insufficient work area to run the program.\n"); - return 1; - } - - for (cc = 1; cc <= ncyc; cc++) { - printf("**** Test cycle %u of %u start ****\n", cc, ncyc); - - printf(" disk_initalize(%u)", pdrv); - ds = disk_initialize(pdrv); - if (ds & STA_NOINIT) { - printf(" - failed.\n"); - return 2; - } else { - printf(" - ok.\n"); - } - - printf("**** Get drive size ****\n"); - printf(" disk_ioctl(%u, GET_SECTOR_COUNT, 0x%08X)", pdrv, (UINT)&sz_drv); - sz_drv = 0; - dr = disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_drv); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - return 3; - } - if (sz_drv < 128) { - printf("Failed: Insufficient drive size to test.\n"); - return 4; - } - printf(" Number of sectors on the drive %u is %lu.\n", pdrv, sz_drv); - -#if FF_MAX_SS != FF_MIN_SS - printf("**** Get sector size ****\n"); - printf(" disk_ioctl(%u, GET_SECTOR_SIZE, 0x%X)", pdrv, (UINT)&sz_sect); - sz_sect = 0; - dr = disk_ioctl(pdrv, GET_SECTOR_SIZE, &sz_sect); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - return 5; - } - printf(" Size of sector is %u bytes.\n", sz_sect); -#else - sz_sect = FF_MAX_SS; -#endif - - printf("**** Get block size ****\n"); - printf(" disk_ioctl(%u, GET_BLOCK_SIZE, 0x%X)", pdrv, (UINT)&sz_eblk); - sz_eblk = 0; - dr = disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_eblk); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - } - if (dr == RES_OK || sz_eblk >= 2) { - printf(" Size of the erase block is %lu sectors.\n", sz_eblk); - } else { - printf(" Size of the erase block is unknown.\n"); - } - - /* Single sector write test */ - printf("**** Single sector write test ****\n"); - lba = 0; - for (n = 0, pn(pns); n < sz_sect; n++) pbuff[n] = (BYTE)pn(0); - printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba); - dr = disk_write(pdrv, pbuff, lba, 1); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - return 6; - } - printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv); - dr = disk_ioctl(pdrv, CTRL_SYNC, 0); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - return 7; - } - memset(pbuff, 0, sz_sect); - printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba); - dr = disk_read(pdrv, pbuff, lba, 1); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - return 8; - } - for (n = 0, pn(pns); n < sz_sect && pbuff[n] == (BYTE)pn(0); n++) ; - if (n == sz_sect) { - printf(" Read data matched.\n"); - } else { - printf(" Read data differs from the data written.\n"); - return 10; - } - pns++; - - printf("**** Multiple sector write test ****\n"); - lba = 5; ns = sz_buff / sz_sect; - if (ns > 4) ns = 4; - if (ns > 1) { - for (n = 0, pn(pns); n < (UINT)(sz_sect * ns); n++) pbuff[n] = (BYTE)pn(0); - printf(" disk_write(%u, 0x%X, %lu, %u)", pdrv, (UINT)pbuff, lba, ns); - dr = disk_write(pdrv, pbuff, lba, ns); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - return 11; - } - printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv); - dr = disk_ioctl(pdrv, CTRL_SYNC, 0); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - return 12; - } - memset(pbuff, 0, sz_sect * ns); - printf(" disk_read(%u, 0x%X, %lu, %u)", pdrv, (UINT)pbuff, lba, ns); - dr = disk_read(pdrv, pbuff, lba, ns); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - return 13; - } - for (n = 0, pn(pns); n < (UINT)(sz_sect * ns) && pbuff[n] == (BYTE)pn(0); n++) ; - if (n == (UINT)(sz_sect * ns)) { - printf(" Read data matched.\n"); - } else { - printf(" Read data differs from the data written.\n"); - return 14; - } - } else { - printf(" Test skipped.\n"); - } - pns++; - - printf("**** Single sector write test (unaligned buffer address) ****\n"); - lba = 5; - for (n = 0, pn(pns); n < sz_sect; n++) pbuff[n+3] = (BYTE)pn(0); - printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+3), lba); - dr = disk_write(pdrv, pbuff+3, lba, 1); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - return 15; - } - printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv); - dr = disk_ioctl(pdrv, CTRL_SYNC, 0); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - return 16; - } - memset(pbuff+5, 0, sz_sect); - printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+5), lba); - dr = disk_read(pdrv, pbuff+5, lba, 1); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - return 17; - } - for (n = 0, pn(pns); n < sz_sect && pbuff[n+5] == (BYTE)pn(0); n++) ; - if (n == sz_sect) { - printf(" Read data matched.\n"); - } else { - printf(" Read data differs from the data written.\n"); - return 18; - } - pns++; - - printf("**** 4GB barrier test ****\n"); - if (sz_drv >= 128 + 0x80000000 / (sz_sect / 2)) { - lba = 6; lba2 = lba + 0x80000000 / (sz_sect / 2); - for (n = 0, pn(pns); n < (UINT)(sz_sect * 2); n++) pbuff[n] = (BYTE)pn(0); - printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba); - dr = disk_write(pdrv, pbuff, lba, 1); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - return 19; - } - printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+sz_sect), lba2); - dr = disk_write(pdrv, pbuff+sz_sect, lba2, 1); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - return 20; - } - printf(" disk_ioctl(%u, CTRL_SYNC, NULL)", pdrv); - dr = disk_ioctl(pdrv, CTRL_SYNC, 0); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - return 21; - } - memset(pbuff, 0, sz_sect * 2); - printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)pbuff, lba); - dr = disk_read(pdrv, pbuff, lba, 1); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - return 22; - } - printf(" disk_read(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+sz_sect), lba2); - dr = disk_read(pdrv, pbuff+sz_sect, lba2, 1); - if (dr == RES_OK) { - printf(" - ok.\n"); - } else { - printf(" - failed.\n"); - return 23; - } - for (n = 0, pn(pns); pbuff[n] == (BYTE)pn(0) && n < (UINT)(sz_sect * 2); n++) ; - if (n == (UINT)(sz_sect * 2)) { - printf(" Read data matched.\n"); - } else { - printf(" Read data differs from the data written.\n"); - return 24; - } - } else { - printf(" Test skipped.\n"); - } - pns++; - - printf("**** Test cycle %u of %u completed ****\n\n", cc, ncyc); - } - - return 0; -} - - -//int main (int argc, char* argv[]) -int lliot(size_t pnum) -{ - int rc; - DWORD buff[FF_MAX_SS]; /* Working buffer (4 sector in size) */ - - /* Check function/compatibility of the physical drive #0 */ - rc = test_diskio(pnum, 3, buff, sizeof buff); - - if (rc) { - printf("Sorry the function/compatibility test failed. (rc=%d)\nFatFs will not work with this disk driver.\n", rc); - } else { - printf("Congratulations! The disk driver works well.\n"); - } - - return rc; -} - diff --git a/examples/command_line/tests/bench.c b/examples/command_line/tests/bench.c deleted file mode 100644 index 9d98951..0000000 --- a/examples/command_line/tests/bench.c +++ /dev/null @@ -1,311 +0,0 @@ -/* Ported from: https://github.com/greiman/SdFat/blob/master/examples/bench/bench.ino - * - * This program is a simple binary write/read benchmark. - */ -#include -#include -#include - -#include "SdCardInfo.h" -#include "SDIO/SdioCard.h" -#include "f_util.h" -#include "ff.h" -#include "hw_config.h" - -#define error(s) \ - { \ - printf("ERROR: %s\n", s); \ - assert(!s); \ - } - -static uint32_t millis() { - return to_ms_since_boot(get_absolute_time()); -} -static uint64_t micros() { - return to_us_since_boot(get_absolute_time()); -} -static sd_card_t* sd_get_by_name(const char* const name) { - for (size_t i = 0; i < sd_get_num(); ++i) - if (0 == strcmp(sd_get_by_num(i)->pcName, name)) return sd_get_by_num(i); - printf("%s: unknown name %s\n", __func__, name); - return NULL; -} - -// Set PRE_ALLOCATE true to pre-allocate file clusters. -static const bool PRE_ALLOCATE = true; - -// Set SKIP_FIRST_LATENCY true if the first read/write to the SD can -// be avoid by writing a file header or reading the first record. -static const bool SKIP_FIRST_LATENCY = true; - -// Size of read/write. -// static const size_t BUF_SIZE = 512; -#define BUF_SIZE (20 * 1024) - -// File size in MiB where MiB = 1048576 bytes. -static const uint32_t FILE_SIZE_MiB = 5; - -// Write pass count. -static const uint8_t WRITE_COUNT = 2; - -// Read pass count. -static const uint8_t READ_COUNT = 2; -//============================================================================== -// End of configuration constants. -//------------------------------------------------------------------------------ -// File size in bytes. -// static const uint32_t FILE_SIZE = 1000000UL * FILE_SIZE_MB; -static const uint32_t FILE_SIZE = (1024 * 1024 * FILE_SIZE_MiB); - -static FIL file; -static sd_card_t* sd_card_p; - -static void cidDmp() { - cid_t cid; - if (!sd_card_p->sd_readCID(sd_card_p, &cid)) { - error("readCID failed"); - } - printf("\nManufacturer ID: "); - // cout << uppercase << showbase << hex << int(cid.mid) << dec << endl; - printf("0x%x\n", cid.mid); - printf("OEM ID: "); - // << cid.oid[0] << cid.oid[1] << endl; - printf("%c%c\n", cid.oid[0], cid.oid[1]); - printf("Product: "); - for (uint8_t i = 0; i < 5; i++) { - printf("%c", cid.pnm[i]); - } - printf("\nRevision: "); - // << cid.prvN() << '.' << cid.prvM() << endl; - // int CID_prvN(cid_t *cid_p) - // int CID_prvM(cid_t *cid_p) - printf("%d.%d\n", CID_prvN(&cid), CID_prvM(&cid)); - printf("Serial number: "); - // << hex << cid.psn() << dec << endl; - // uint32_t CID_psn(cid_t *cid_p) - printf("0x%lx\n", CID_psn(&cid)); - printf("Manufacturing date: "); - // cout << cid.mdtMonth() << '/' << cid.mdtYear() << endl; - // int CID_mdtMonth(cid_t *cid_p) - // int CID_mdtYear(cid_t *cid_p) - printf("%d/%d\n", CID_mdtMonth(&cid), CID_mdtYear(&cid)); - // cout << endl; - printf("\n"); -} -//------------------------------------------------------------------------------ -void bench(char const* logdrv) { - float s; - uint32_t t; - uint32_t maxLatency; - uint32_t minLatency; - uint32_t totalLatency; - bool skipLatency; - - static_assert(0 == FILE_SIZE % BUF_SIZE, - "For accurate results, FILE_SIZE must be a multiple of BUF_SIZE."); - - // Insure 4-byte alignment. - uint32_t buf32[(BUF_SIZE + 3) / 4] __attribute__ ((aligned (4))); - uint8_t* buf = (uint8_t*)buf32; - - sd_card_p = sd_get_by_name(logdrv); - if (!sd_card_p) { - printf("Unknown logical drive name: %s\n", logdrv); - return; - } - FRESULT fr = f_chdrive(logdrv); - if (FR_OK != fr) { - printf("f_chdrive error: %s (%d)\n", FRESULT_str(fr), fr); - return; - } - // if (sd.fatType() == FAT_TYPE_EXFAT) { - // printf("Type is exFAT\n"); - // } else { - // printf("Type is FAT") << int(sd.fatType()) << endl; - // } - switch (sd_card_p->fatfs.fs_type) { - case FS_EXFAT: - printf("Type is exFAT\n"); - break; - case FS_FAT12: - printf("Type is FAT12\n"); - break; - case FS_FAT16: - printf("Type is FAT16\n"); - break; - case FS_FAT32: - printf("Type is FAT32\n"); - break; - } - - printf("Card size: "); - // << sd.card()->sectorCount() * 512E-9; - printf("%.2f", sd_card_p->get_num_sectors(sd_card_p) * 512E-9); - printf(" GB (GB = 1E9 bytes)\n"); - - cidDmp(); - - // open or create file - truncate existing file. - // if (!file.open("bench.dat", O_RDWR | O_CREAT | O_TRUNC)) { - // error("open failed"); - // } - fr = f_open(&file, "bench.dat", FA_READ | FA_WRITE | FA_CREATE_ALWAYS); - if (FR_OK != fr) { - printf("f_open error: %s (%d)\n", FRESULT_str(fr), fr); - return; - } - - // fill buf with known data - if (BUF_SIZE > 1) { - for (size_t i = 0; i < (BUF_SIZE - 2); i++) { - buf[i] = 'A' + (i % 26); - } - buf[BUF_SIZE - 2] = '\r'; - } - buf[BUF_SIZE - 1] = '\n'; - - printf("FILE_SIZE_MB = %lu\n", FILE_SIZE_MiB); // << FILE_SIZE_MB << endl; - printf("BUF_SIZE = %zu\n", BUF_SIZE); // << BUF_SIZE << F(" bytes\n"); - printf("Starting write test, please wait.\n\n"); // << endl - // << endl; - // do write test - uint32_t n = FILE_SIZE / BUF_SIZE; - printf("write speed and latency\n"); - printf("speed,max,min,avg\n"); - printf("KB/Sec,usec,usec,usec\n"); - for (uint8_t nTest = 0; nTest < WRITE_COUNT; nTest++) { - // file.truncate(0); - // Open with FA_CREATE_ALWAYS creates a new file, - // and if the file is existing, it will be truncated and overwritten. - if (PRE_ALLOCATE) { - // if (!file.preAllocate(FILE_SIZE)) { - // error("preAllocate failed"); - // } - fr = f_lseek(&file, FILE_SIZE); - if (FR_OK != fr) { - printf("f_lseek error: %s (%d)\n", FRESULT_str(fr), fr); - return; - } - if (f_tell(&file) != FILE_SIZE) { - printf("Disk full!\n"); - return; - } - fr = f_rewind(&file); - if (FR_OK != fr) { - printf("f_rewind error: %s (%d)\n", FRESULT_str(fr), fr); - return; - } - } - maxLatency = 0; - minLatency = 9999999; - totalLatency = 0; - skipLatency = SKIP_FIRST_LATENCY; - t = millis(); - for (uint32_t i = 0; i < n; i++) { - uint32_t m = micros(); - - // if (file.write(buf, BUF_SIZE) != BUF_SIZE) { - // error("write failed"); - // } - unsigned int bw; - fr = f_write(&file, buf, BUF_SIZE, &bw); /* Write it to the destination file */ - if (FR_OK != fr) { - printf("f_rewind error: %s (%d)\n", FRESULT_str(fr), fr); - return; - } - if (bw < BUF_SIZE) { /* error or disk full */ - error("write failed"); - } - m = micros() - m; - totalLatency += m; - if (skipLatency) { - // Wait until first write to SD, not just a copy to the cache. - // skipLatency = file.curPosition() < 512; - skipLatency = f_tell(&file) < 512; - } else { - if (maxLatency < m) { - maxLatency = m; - } - if (minLatency > m) { - minLatency = m; - } - } - } - // file.sync(); - fr = f_sync(&file); - if (FR_OK != fr) { - printf("f_sync error: %s (%d)\n", FRESULT_str(fr), fr); - return; - } - t = millis() - t; - // s = file.fileSize(); - s = f_size(&file); - // cout << s / t << ',' << maxLatency << ',' << minLatency; - printf("%.1f,%lu,%lu", s / t, maxLatency, minLatency); - // cout << ',' << totalLatency / n << endl; - printf(",%lu\n", totalLatency / n); - } - printf("\nStarting read test, please wait.\n"); - printf("\nread speed and latency\n"); - printf("speed,max,min,avg\n"); - printf("KB/Sec,usec,usec,usec\n"); - - // do read test - for (uint8_t nTest = 0; nTest < READ_COUNT; nTest++) { - // file.rewind(); - fr = f_rewind(&file); - if (FR_OK != fr) { - printf("f_rewind error: %s (%d)\n", FRESULT_str(fr), fr); - return; - } - maxLatency = 0; - minLatency = 9999999; - totalLatency = 0; - skipLatency = SKIP_FIRST_LATENCY; - t = millis(); - for (uint32_t i = 0; i < n; i++) { - buf[BUF_SIZE - 1] = 0; - uint32_t m = micros(); - // int32_t nr = file.read(buf, BUF_SIZE); - unsigned int nr; - fr = f_read(&file, buf, BUF_SIZE, &nr); - if (FR_OK != fr) { - printf("f_read error: %s (%d)\n", FRESULT_str(fr), fr); - return; - } - if (nr != BUF_SIZE) { - error("read failed"); - } - m = micros() - m; - totalLatency += m; - if (buf[BUF_SIZE - 1] != '\n') { - error("data check error"); - } - if (skipLatency) { - skipLatency = false; - } else { - if (maxLatency < m) { - maxLatency = m; - } - if (minLatency > m) { - minLatency = m; - } - } - } - // s = file.fileSize(); - s = f_size(&file); - t = millis() - t; - // cout << s / t << ',' << maxLatency << ',' << minLatency; - printf("%.1f,%lu,%lu", s / t, maxLatency, minLatency); - // cout << ',' << totalLatency / n << endl; - printf(",%lu\n", totalLatency / n); - } - printf("\nDone\n"); - // file.close(); - fr = f_close(&file); - if (FR_OK != fr) { - printf("f_close error: %s (%d)\n", FRESULT_str(fr), fr); - return; - } - // sd.end(); -} diff --git a/examples/command_line/tests/big_file_test.c b/examples/command_line/tests/big_file_test.c deleted file mode 100644 index 3f6c746..0000000 --- a/examples/command_line/tests/big_file_test.c +++ /dev/null @@ -1,182 +0,0 @@ -/* big_file_test.c -Copyright 2021 Carl John Kugler III - -Licensed under the Apache License, Version 2.0 (the License); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at - - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software distributed -under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR -CONDITIONS OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. -*/ - -#include -#include -#include -#include -#include -#include -#include -// -#include "pico/stdlib.h" -// -#include "ff.h" -#include "f_util.h" - -#define FF_MAX_SS 512 -#define BUFFSZ (32 * FF_MAX_SS) // Should be a factor of 1 Mebibyte - -#define PRE_ALLOCATE false - -typedef uint32_t DWORD; -typedef unsigned int UINT; - -// Create a file of size "size" bytes filled with random data seeded with "seed" -static bool create_big_file(const char *const pathname, uint64_t size, - unsigned seed, DWORD *buff) { - FRESULT fr; - FIL file; /* File object */ - - srand(seed); // Seed pseudo-random number generator - - printf("Writing...\n"); - absolute_time_t xStart = get_absolute_time(); - - /* Open the file, creating the file if it does not already exist. */ - FILINFO fno; - size_t fsz = 0; - fr = f_stat(pathname, &fno); - if (FR_OK == fr) - fsz = fno.fsize; - if (0 < fsz && fsz <= size) { - // This is an attempt at optimization: - // rewriting the file should be faster than - // writing it from scratch. - fr = f_open(&file, pathname, FA_READ | FA_WRITE); - if (FR_OK != fr) { - printf("f_open error: %s (%d)\n", FRESULT_str(fr), fr); - return false; - } - fr = f_rewind(&file); - if (FR_OK != fr) { - printf("f_rewind error: %s (%d)\n", FRESULT_str(fr), fr); - return false; - } - } else { - fr = f_open(&file, pathname, FA_WRITE | FA_CREATE_ALWAYS); - if (FR_OK != fr) { - printf("f_open error: %s (%d)\n", FRESULT_str(fr), fr); - return false; - } - } - if (PRE_ALLOCATE) { - FRESULT fr = f_lseek(&file, size); - if (FR_OK != fr) { - printf("f_lseek error: %s (%d)\n", FRESULT_str(fr), fr); - return false; - } - if (f_tell(&file) != size) { - printf("Disk full?\n"); - return false; - } - fr = f_rewind(&file); - if (FR_OK != fr) { - printf("f_rewind error: %s (%d)\n", FRESULT_str(fr), fr); - return false; - } - } - for (uint64_t i = 0; i < size / BUFFSZ; ++i) { - size_t n; - for (n = 0; n < BUFFSZ / sizeof(DWORD); n++) buff[n] = rand(); - UINT bw; - fr = f_write(&file, buff, BUFFSZ, &bw); - if (bw < BUFFSZ) { - printf("f_write(%s,,%d,): only wrote %d bytes\n", pathname, BUFFSZ, bw); - return false; - } - if (FR_OK != fr) { - printf("f_write error: %s (%d)\n", FRESULT_str(fr), fr); - return false; - } - } - /* Close the file */ - f_close(&file); - - int64_t elapsed_us = absolute_time_diff_us(xStart, get_absolute_time()); - float elapsed = elapsed_us / 1E6; - printf("Elapsed seconds %.3g\n", elapsed); - printf("Transfer rate %.3g KiB/s (%.3g kB/s) (%.3g kb/s)\n", - (double)size / elapsed / 1024, (double)size / elapsed / 1000, 8.0 * size / elapsed / 1000); - return true; -} - -// Read a file of size "size" bytes filled with random data seeded with "seed" -// and verify the data -static bool check_big_file(char *pathname, uint64_t size, - uint32_t seed, DWORD *buff) { - FRESULT fr; - FIL file; /* File object */ - - srand(seed); // Seed pseudo-random number generator - - fr = f_open(&file, pathname, FA_READ); - if (FR_OK != fr) { - printf("f_open error: %s (%d)\n", FRESULT_str(fr), fr); - return false; - } - printf("Reading...\n"); - absolute_time_t xStart = get_absolute_time(); - - for (uint64_t i = 0; i < size / BUFFSZ; ++i) { - UINT br; - fr = f_read(&file, buff, BUFFSZ, &br); - if (br < BUFFSZ) { - printf("f_read(,%s,%d,):only read %u bytes\n", pathname, BUFFSZ, br); - return false; - } - if (FR_OK != fr) { - printf("f_read error: %s (%d)\n", FRESULT_str(fr), fr); - return false; - } - /* Check the buffer is filled with the expected data. */ - size_t n; - for (n = 0; n < BUFFSZ / sizeof(DWORD); n++) { - unsigned int expected = rand(); - unsigned int val = buff[n]; - if (val != expected) { - printf("Data mismatch at dword %llu: expected=0x%8x val=0x%8x\n", - (i * sizeof(buff)) + n, expected, val); - return false; - } - } - } - /* Close the file */ - f_close(&file); - - int64_t elapsed_us = absolute_time_diff_us(xStart, get_absolute_time()); - float elapsed = elapsed_us / 1E6; - printf("Elapsed seconds %.3g\n", elapsed); - printf("Transfer rate %.3g KiB/s (%.3g kB/s) (%.3g kb/s)\n", - (double)size / elapsed / 1024, (double)size / elapsed / 1000, 8.0 * size / elapsed / 1000); - return true; -} -// Specify size in Mebibytes (1024x1024 bytes) -void big_file_test(char * pathname, size_t size_MiB, uint32_t seed) { - // /* Working buffer */ - DWORD *buff = malloc(BUFFSZ); - assert(buff); - assert(size_MiB); - if (4095 < size_MiB) { - printf("Warning: Maximum file size: 2^32 - 1 bytes on FAT volume\n"); - } - uint64_t size_B = (uint64_t)size_MiB * 1024 * 1024; - - if (create_big_file(pathname, size_B, seed, buff)) - check_big_file(pathname, size_B, seed, buff); - - free(buff); -} - -/* [] END OF FILE */ diff --git a/examples/command_line/tests/ff_stdio_tests_with_cwd.c b/examples/command_line/tests/ff_stdio_tests_with_cwd.c deleted file mode 100644 index db3e49e..0000000 --- a/examples/command_line/tests/ff_stdio_tests_with_cwd.c +++ /dev/null @@ -1,1196 +0,0 @@ -/* ff_stdio_tests_with_cwd.c -Copyright 2021 Carl John Kugler III - -Licensed under the Apache License, Version 2.0 (the License); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at - - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software distributed -under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR -CONDITIONS OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. -*/ -/* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. - All rights reserved - - VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. - - *************************************************************************** - >>! NOTE: The modification to the GPL is included to allow you to !<< - >>! distribute a combined work that includes FreeRTOS without being !<< - >>! obliged to provide the source code for proprietary components !<< - >>! outside of the FreeRTOS kernel. !<< - *************************************************************************** - - FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. Full license text is available on the following - link: http://www.freertos.org/a00114.html - - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that is more than just the market leader, it * - * is the industry's de facto standard. * - * * - * Help yourself get started quickly while simultaneously helping * - * to support the FreeRTOS project by purchasing a FreeRTOS * - * tutorial book, reference manual, or both: * - * http://www.FreeRTOS.org/Documentation * - * * - *************************************************************************** - - http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading - the FAQ page "My application does not run, what could be wrong?". Have you - defined configASSERT()? - - http://www.FreeRTOS.org/support - In return for receiving this top quality - embedded software for free we request you assist our global community by - participating in the support forum. - - http://www.FreeRTOS.org/training - Investing in training allows your team to - be as productive as possible as early as possible. Now you can receive - FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers - Ltd, and the world's leading authority on the world's leading RTOS. - - http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, - including FreeRTOS+Trace - an indispensable productivity tool, a DOS - compatible FAT file system, and our tiny thread aware UDP/IP stack. - - http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. - Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. - - http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High - Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and commercial middleware. - - http://www.SafeRTOS.com - High Integrity Systems also provide a safety - engineered and independently SIL3 certified version for use in safety and - mission critical applications that require provable dependability. - - 1 tab == 4 spaces! -*/ - -/* - * Non-systematic sanity checks for the API defined in ff_stdio.c. - */ -#include -#include - -/* FreeRTOS+FAT headers. */ -//#include "ff_headers.h" -#include "ff_stdio.h" - -/* The number of bytes read/written to the example files at a time. */ -#define fsRAM_BUFFER_SIZE 200 - -/* The number of bytes written to the file that uses f_putc() and f_getc(). */ -#define fsPUTC_FILE_SIZE 100 - -/* The number of tasks to create if the stdio tests will be executed in -multiple tasks simultaneously. */ -//#define fsTASKS_TO_CREATE 5 -#define fsTASKS_TO_CREATE 2 - -//#include "hardware/gpio.h" //DEBUG -//#define TRACE_PRINTF(fmt, args...) -#define TRACE_PRINTF printf - -/* - * Examples and basic tests of the ff_truncate() function. - */ -static void prvTest_ff_truncate( const char *pcMountPath ); - -/* - * Examples and basic tests of the ff_findNNN() functions. - */ -static void prvTest_ff_findfirst_ff_findnext_ff_findclose( const char *pcMountPath ); - -/* - * Examples and basic tests of the ff_fopen() function. - */ -static void prvTest_ff_fopen( const char *pcMountPath ); - -/* - * Examples and basic tests of the ff_rename() function. - */ -static void prvTest_ff_rename( const char *pcMountPath ); - -/* - * Examples and basic tests of the ff_mkdir, ff_chdir() and ff_rmdir() - * functions. - */ -static void prvTest_ff_fmkdir_ff_chdir_ff_rmdir( const char *pcMountPath ); - -/* - * Non-systematic sanity check that aligned and unaligned data can be written - * within and across sectors. - */ -static void prvTest_ff_fseek_ff_rewind( const char *pcMountPath ); - -/* - * Examples and basic tests of the ff_fgets() function. - */ -#if( ffconfigFPRINTF_SUPPORT == 1 ) - - static void prvTest_ff_fgets_ff_printf( const char *pcMountPath ); - -#endif /* ffconfigFPRINTF_SUPPORT */ - -/* - * Non-systematic sanity check that aligned and unaligned data can be written - * within and across sectors. - */ -static void prvAlignmentReadWriteTests( const char *pcMountPath ); - -/* - * A task that repeatedly creates, tests, then deletes files as an ad hoc test - * of accessing the file system from more than one task simultaneously. - */ -// static void prvFileSystemAccessTask( void *pvParameters ); - -/*-----------------------------------------------------------*/ - -void vStdioWithCWDTest( const char *pcMountPath ) -{ - TRACE_PRINTF("%s(pcMountPath=%s)\n", __FUNCTION__, pcMountPath); - - /* Non-systematic sanity checks for the API defined in ff_stdio.c. */ - - /* Must come after the prvCreateDemoFilesUsing_fwrite() and - prvCreateDemoFileUsing_fputc() functions as it expects the files created by - those functions to exist. */ - - prvTest_ff_findfirst_ff_findnext_ff_findclose( pcMountPath ); - - prvTest_ff_truncate( pcMountPath ); - - prvTest_ff_fmkdir_ff_chdir_ff_rmdir( pcMountPath ); - - prvTest_ff_fopen( pcMountPath ); - - prvTest_ff_rename( pcMountPath ); - - prvAlignmentReadWriteTests( pcMountPath ); - - prvTest_ff_fseek_ff_rewind( pcMountPath ); - - #if( ffconfigFPRINTF_SUPPORT == 1 ) - { - prvTest_ff_fgets_ff_printf( pcMountPath ); - } - #endif -} -/*-----------------------------------------------------------*/ - -static void prvTest_ff_fmkdir_ff_chdir_ff_rmdir( const char *pcMountPath ) -{ - TRACE_PRINTF("%s(pcMountPath=%s)\n", __FUNCTION__, pcMountPath); - -int iReturned; -char *pcRAMBuffer, *pcFileName; - - /* Allocate buffers used to hold date written to/from the disk, and the - file names. */ - pcRAMBuffer = ( char * ) pvPortMalloc( fsRAM_BUFFER_SIZE ); - pcFileName = ( char * ) pvPortMalloc( ffconfigMAX_FILENAME ); - configASSERT( pcRAMBuffer ); - configASSERT( pcFileName ); - - /* Try changing to an invalid absolute directory. This should fail. */ - iReturned = ff_chdir( "/not_a_directory" ); - configASSERT( iReturned == -1 ); - - /* Try changing to the root. This should not fail. */ - iReturned = ff_chdir( "/" ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - /* Try changing to an invalid relative directory. This should also fail. */ - iReturned = ff_chdir( "not_a_directory" ); - configASSERT( iReturned == -1 ); - - /* Ensure in the root of the mount being used. */ - iReturned = ff_chdir( pcMountPath ); - - /* This time the directory should have been entered. */ - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - /* For test purposes, move back, then try moving to the root of the mount - using a relative path. */ - iReturned = ff_chdir( "/" ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - /* Ensure in the root of the mount being used but using a relative path, - so move past the '/' at the beginning of pcMountPath. */ - iReturned = ff_chdir( pcMountPath + 1 ); - - /* This time the directory should have been entered. */ - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - /* Create nested subdirectories from the root of the mount. */ - iReturned = ff_mkdir( "sub1" ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - iReturned = ff_mkdir( "sub1/sub2" ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - iReturned = ff_mkdir( "sub1/sub2/sub3" ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - //iReturned = ff_mkdir( "sub1/sub2/sub3/sub4/" ); - iReturned = ff_mkdir( "sub1/sub2/sub3/sub4" ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - /* This is the non-recursive version, so the following is expected to - fail. */ - iReturned = ff_mkdir( "sub1/sub2/subx/suby" ); - configASSERT( iReturned == -1 ); - - /* Move into sub3. */ - iReturned = ff_chdir( "sub1/sub2/sub3" ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - /* Make more directories using relative paths. */ - iReturned = ff_mkdir( "../../sub2/sub3/sub4/sub5" ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - /* Sub6 does not exist, expect this to fail. */ - iReturned = ff_chdir( "../../sub2/sub3/sub4/sub6" ); - configASSERT( iReturned == -1 ); - - /* Sub5 does exist, expect this to pass. */ - iReturned = ff_chdir( "../../sub2/../../sub1/sub2/sub3/../sub3/sub4/sub5" ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - /* Create a string that contains the expected CWD. */ - snprintf( pcRAMBuffer, fsRAM_BUFFER_SIZE, "%s/%s", pcMountPath, "sub1/sub2/sub3/sub4/sub5" ); - - /* Attempt to get the CWD, but using a buffer too small. There is no room - for the NULL terminator in the line below. */ - configASSERT( ff_getcwd( pcFileName, strlen( pcRAMBuffer ) ) == NULL ); - - /* Ensure the CWD is as expected. */ - configASSERT( ff_getcwd( pcFileName, ffconfigMAX_FILENAME ) == pcFileName ); - //configASSERT( strcmp( pcFileName, pcRAMBuffer ) == 0 ); - configASSERT( strcasecmp( pcFileName, pcRAMBuffer ) == 0 ); - - /* Should not be possible to delete a directory in the CWD (although it is - possible to delete the CWD if it is empty!). */ - iReturned = ff_rmdir( "../../sub4" ); - configASSERT( iReturned == -1 ); - - /* It should be possible to remove sub5 as it does not contain anything. */ - iReturned = ff_chdir( "../.." ); - configASSERT( iReturned == 0 ); - iReturned = ff_rmdir( "sub4/sub5" ); - configASSERT( iReturned == 0 ); - - /* Should not now be possible to move to sub4/sub5. */ - iReturned = ff_chdir( "sub4/sub5" ); - configASSERT( iReturned == -1 ); - - /* Still possible to move to sub4 though. */ - iReturned = ff_chdir( "sub4" ); - configASSERT( iReturned == 0 ); - - vPortFree( pcRAMBuffer ); - vPortFree( pcFileName ); -} -/*-----------------------------------------------------------*/ - -#if( ffconfigFPRINTF_SUPPORT == 1 ) - - static void prvTest_ff_fgets_ff_printf( const char *pcMountPath ) - { - FF_FILE *pxFile; - int iReturned, iString; - const char *const pcTestFileName = "TestFile.txt"; - const char *const pcStringStart = "Test string"; - const int iMaxStrings = 1000; - char pcReadString[ 17 ], pcExpectedString[ 17 ], *pcReturned; - const char *pcMaximumStringLength = "Test string 999\n"; - - /* For coverage this test wants the buffers to be exactly equal to the - maximum string length. A one is added as the string must also hold the - null terminator. */ - configASSERT( ( strlen( pcMaximumStringLength ) + 1 ) == sizeof( pcReadString ) ); - - /* Move to the root of the mount. */ - iReturned = ff_chdir( pcMountPath ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - /* Open a test file for writing. */ - pxFile = ff_fopen( pcTestFileName, "w+" ); - if (!pxFile) { - FF_PRINTF("ff_fopen error: %s (%d)\n", strerror(errno), errno); - configASSERT( pxFile ); - } - /* Write the strings to the file. */ - for( iString = 0; iString < iMaxStrings; iString++ ) - { - /* Call ff_fprintf() to write the formatted string to the file. */ - iReturned = ff_fprintf( pxFile, "%s %d\n", pcStringStart, iString ); - - /* Generate the expected string so the return value of ff_fprintf() - can be checked. */ - sprintf( pcExpectedString, "%s %d\n", pcStringStart, iString ); - configASSERT( iReturned == ( int ) strlen( pcExpectedString ) ); - } - - /* Read back and check the strings. */ - ff_rewind( pxFile ); - configASSERT( ff_ftell( pxFile ) == 0 ); - - for( iString = 0; iString < iMaxStrings; iString++ ) - { - /* Generate the expected string. */ - sprintf( pcExpectedString, "%s %d\n", pcStringStart, iString ); - - /* Read back the next string. */ - memset( pcReadString, 0x00, sizeof( pcReadString ) ); - pcReturned = ff_fgets( pcReadString, sizeof( pcReadString ), pxFile ); - - /* The string should have been read back successfully. */ - configASSERT( pcReturned == pcReadString ); - configASSERT( strcmp( pcReadString, pcExpectedString ) == 0 ); - } - - /* Should be at the end of the file now. */ - configASSERT( ff_feof( pxFile ) != 0 ); - - /* Asking for one byte should always pass because the single byte will - just be the NULL terminator, but asking for two bytes should fail as the - EOF has been reached. */ - configASSERT( ff_fgets( pcReadString, 1, pxFile ) == pcReadString ); - configASSERT( strlen( pcReadString ) == 0 ); - configASSERT( ff_fgets( pcReadString, 2, pxFile ) == NULL ); - - /* Back to the start. */ - configASSERT( ff_feof( pxFile ) != 0 ); - iReturned = ff_fseek( pxFile, 0, FF_SEEK_SET ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - configASSERT( ff_ftell( pxFile ) == 0 ); - configASSERT( ff_feof( pxFile ) == 0 ); - - /* This time don't read all the way to a newline. Just read the string - without the number on the end. The +1 is included to accommodate the - NULL terminator. */ - pcReturned = ff_fgets( pcReadString, strlen( pcStringStart ) + 1, pxFile ); - - /* The read should have been successful. */ - configASSERT( pcReturned == pcReadString ); - configASSERT( strcmp( pcReadString, pcStringStart ) == 0 ); - - /* Move to the end of the file. */ - iReturned = ff_fseek( pxFile, 0, FF_SEEK_END ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - /* Write a string without a \n on the end. */ - ff_fprintf( pxFile, pcStringStart ); - - /* Now seek back and read some characters while attempting to read off - the end of the file. */ - iReturned = ff_fseek( pxFile, 0 - (int ) strlen( pcStringStart ), FF_SEEK_CUR ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - pcReturned = ff_fgets( pcReadString, sizeof( pcReadString ), pxFile ); - /* pcReturned will contain the last string "Test string", without a linefeed. */ - configASSERT( pcReturned == pcReadString ); - configASSERT( strcmp( pcReadString, pcStringStart ) == 0 ); - - pcReturned = ff_fgets( pcReadString, sizeof( pcReadString ), pxFile ); - /* pcReturned will be NULL because EOF has been reached. */ - configASSERT( pcReturned == NULL ); - - ff_fclose( pxFile ); - } - -#endif /* ffconfigFPRINTF_SUPPORT */ -/*-----------------------------------------------------------*/ - -static void prvTest_ff_fseek_ff_rewind( const char *pcMountPath ) -{ - TRACE_PRINTF("%s(pcMountPath=%s)\n", __FUNCTION__, pcMountPath); - -FF_FILE *pxFile; -int iReturned; -const size_t xFileSize = 7776UL; -const size_t xNum32BitValues = xFileSize / sizeof( uint32_t ); -uint32_t x, y; - - /* Move to the root of the mount. */ - iReturned = ff_chdir( pcMountPath ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - /* Ensure the file does not already exist. */ - ff_remove( "seek_rewind_test_file" ); - - /* Open a test file. */ - pxFile = ff_fopen( "seek_rewind_test_file", "a+" ); - configASSERT( pxFile ); - - /* Fill the file with known data. */ - for( x = 0; x < xNum32BitValues; x++ ) - { - iReturned = ff_fwrite( &x, 1, sizeof( x ), pxFile ); - configASSERT( iReturned == sizeof( uint32_t ) ); - configASSERT( ff_ftell( pxFile ) == ( long ) ( ( x + 1U ) * sizeof( uint32_t ) ) ); - } - - /* Use rewind to get back to the beginning of the file. */ - ff_rewind( pxFile ); - configASSERT( ff_ftell( pxFile ) == 0 ); - - /* Expect 0 to be read from the start. */ - iReturned = ff_fread( &x, 1, sizeof( x ), pxFile ); - configASSERT( iReturned == sizeof( x ) ); - configASSERT( x == 0 ); - - /* Move to the end of the file. */ - iReturned = ff_fseek( pxFile, 0, FF_SEEK_END ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - configASSERT( ff_ftell( pxFile ) == ( long ) xFileSize ); - - /* Try moving past the front of the file. An error should be returned and - the position should not change. */ - iReturned = ff_fseek( pxFile, 0 - ( ( long ) xFileSize * 2 ), FF_SEEK_END ); - configASSERT( iReturned != pdFREERTOS_ERRNO_NONE ); - configASSERT( ff_ftell( pxFile ) == ( long ) xFileSize ); - - /* Reading from here should fail (EOF). */ - iReturned = ( int ) ff_fread( &x, 1, 1, pxFile ); - configASSERT( iReturned == 0 ); - - /* Now go backwards through the file, reading each uint32_t on the way. */ - for( y = ( xNum32BitValues - 1 ); y >= sizeof( uint32_t ); y -= sizeof( x ) ) - { - iReturned = ff_fseek( pxFile, ( long ) y * sizeof( uint32_t ), FF_SEEK_SET ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - configASSERT( ff_ftell( pxFile ) == ( long ) ( y * sizeof( uint32_t ) ) ); - - /* Data read from here should equal the position. */ - iReturned = ( int ) ff_fread( &x, 1, sizeof( x ), pxFile ); - configASSERT( iReturned == sizeof( x ) ); - configASSERT( x == y ); - } - - /* Move forward through the file doing the same thing. Start at the - front. */ - iReturned = ff_fseek( pxFile, 0 - ( ( long ) xFileSize ), FF_SEEK_END ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - configASSERT( ff_ftell( pxFile ) == ( long ) 0 ); - - for( y = 0; y < xNum32BitValues; y++ ) - { - iReturned = ff_fseek( pxFile, ( long ) ( y * sizeof( x ) ), FF_SEEK_CUR ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - configASSERT( ff_ftell( pxFile ) == ( long ) ( y * sizeof( uint32_t ) ) ); - - /* Data read from here should equal the position. */ - iReturned = ( int ) ff_fread( &x, 1, sizeof( x ), pxFile ); - configASSERT( iReturned == sizeof( x ) ); - configASSERT( x == y ); - - /* Move back to the start of the file. */ - iReturned = ff_fseek( pxFile, 0 - ( long ) ( ( y + 1 ) * sizeof( x ) ), FF_SEEK_CUR ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - configASSERT( ff_ftell( pxFile ) == 0 ); - } - - ff_fclose( pxFile ); -} -/*-----------------------------------------------------------*/ - -static void prvTest_ff_findfirst_ff_findnext_ff_findclose( const char* pcMountPath ) -{ - TRACE_PRINTF("%s(pcMountPath=%s)\n", __FUNCTION__, pcMountPath); -int iReturned; -size_t i; -uint8_t ucFoundFiles[ 6 ]; -FF_FindData_t *pxFindStruct = NULL; -const char *pcExpectedRootFiles[] = -{ - //".", - //"..", - "SUB1", - "root001.txt", - "root002.txt", - "root003.txt", - "root004.txt", - "root005.txt" -}; - -const char *pcExpectedSUB1Files[] = -{ - //".", - //"..", - "SUB2", -}; - - /* There should be one place in the ucFoundFiles[] array for every place in - the pcExpectedRootFiles[] array. */ - configASSERT( sizeof( ucFoundFiles ) == ( sizeof( pcExpectedRootFiles ) / sizeof( char * ) ) ); - - /* No files found yet. */ - memset( ucFoundFiles, 0x00, sizeof( ucFoundFiles ) ); - - /* Move to the root of the mount. */ - iReturned = ff_chdir( pcMountPath ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - /* FF_FindData_t is quite large, so best to malloc() it on stack challenged - architectures. */ - pxFindStruct = ( FF_FindData_t * ) pvPortMalloc( sizeof( FF_FindData_t ) ); - configASSERT( pxFindStruct ); - - if( pxFindStruct != NULL ) - { - /* Must be initialised to 0. */ - memset( pxFindStruct, 0x00, sizeof( FF_FindData_t ) ); - - /* The first parameter to ff_findfist() is the directory being searched, - wildcards are not (currently) supported, so as this is searching the - current working directory the string is empty. */ - if( ff_findfirst( "", pxFindStruct ) == pdFREERTOS_ERRNO_NONE ) - { - do - { - /* Which file was found? */ - for( i = 0; i < sizeof( ucFoundFiles ); i++ ) - { - if( strcmp( pcExpectedRootFiles[ i ], pxFindStruct->pcFileName ) == 0 ) - { - /* The file at this index was found. */ - ucFoundFiles[ i ] = pdTRUE; - break; - } - } - - } while( ff_findnext( pxFindStruct ) == pdFREERTOS_ERRNO_NONE ); - } - f_closedir(&pxFindStruct->dir); - - /* Were all the files found? */ - for( i = 0; i < sizeof( ucFoundFiles ); i++ ) - { - configASSERT( ucFoundFiles[ i ] == pdTRUE ); - } - - - /* Next check a file can be read from the SUB1 directory. First reset - the FF_FindData_t structure. */ - memset( pxFindStruct, 0x00, sizeof( FF_FindData_t ) ); - memset( ucFoundFiles, 0x00, sizeof( ucFoundFiles ) ); - - if( ff_findfirst( "SUB1", pxFindStruct ) == pdFREERTOS_ERRNO_NONE ) - { - do - { - /* Which file was found? */ - for( i = 0; i < ( sizeof( pcExpectedSUB1Files ) / sizeof( char * ) ); i++ ) - { - if( strcmp( pcExpectedSUB1Files[ i ], pxFindStruct->pcFileName ) == 0 ) - { - /* The file at this index was found. */ - ucFoundFiles[ i ] = pdTRUE; - break; - } - } - - } while( ff_findnext( pxFindStruct ) == pdFREERTOS_ERRNO_NONE ); - } - f_closedir(&pxFindStruct->dir); - - /* Were all the files found? */ - for( i = 0; i < ( sizeof( pcExpectedSUB1Files ) / sizeof( char * ) ); i++ ) - { - configASSERT( ucFoundFiles[ i ] == pdTRUE ); - } - - /* Must free the find struct again. */ - vPortFree( pxFindStruct ); - } -} -/*-----------------------------------------------------------*/ - -static void prvTest_ff_truncate( const char *pcMountPath ) -{ - TRACE_PRINTF("%s(pcMountPath=%s)\n", __FUNCTION__, pcMountPath); - -int iReturned, x; -FF_FILE *pxFile; -/*_RB_ Cannot have / on end due to ff_findfirst() being using if ff_stat(). The -original file name has to be used at one point as both the findfirst() and fstat() -functions both use the thread local file name, and having the / on the end prevents -strcmp being used const char * const pcTestFileName = "truncate.bin/"; */ -const char * const pcTestFileName = "truncate.bin"; -FF_Stat_t xStat; -int cChar; - - /* Move to the root of the mount. */ - iReturned = ff_chdir( pcMountPath ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - /* Ensure the file does not already exist. */ - ff_remove( pcTestFileName ); - - /* This time the file definitely should not exist. */ - configASSERT( ff_remove( pcTestFileName ) == -1 ); - - /* Try closing the file before it is opened. */ - pxFile = NULL; - configASSERT( ff_fclose( pxFile ) == -1 ); - - /* Create a 1000 byte file. */ - pxFile = ff_truncate( pcTestFileName, 1000L ); - - /* Check the file has the expected size. */ - ff_fclose( pxFile ); - ff_stat( pcTestFileName, &xStat ); - configASSERT( xStat.st_size == 1000L ); - - /* The file should have been created full of zeros. */ - pxFile = ff_fopen( pcTestFileName, "r" ); - configASSERT( pxFile != NULL ); - - /* Calling ff_filelength() should pass as the file is not read only. */ - configASSERT( ff_filelength( pxFile ) == 1000 ); - - /* Should not be able to write now. */ - iReturned = ff_fputc( 0xff, pxFile ); - configASSERT( iReturned != 0xff ); - - for( x = 0; x < 1000; x++ ) - { - cChar = ff_fgetc( pxFile ); - configASSERT( cChar == 0 ); - } - - /* Should now be at the end of the file. */ - configASSERT( ff_fgetc( pxFile ) == FF_EOF ); - configASSERT( ff_feof( pxFile ) != 0 ); - - /* ff_seteof() should fail as the file is read only. As should - ff_fprintf(). */ - configASSERT( ff_seteof( pxFile ) == -1 ); - #if( ffconfigFPRINTF_SUPPORT != 0 ) - { - configASSERT( ff_fprintf( pxFile, "this should fail" ) == -1 ); - } - #endif - - /* Fill the file with 0xff. */ - ff_fclose( pxFile ); - pxFile = ff_fopen( pcTestFileName, "r+" ); - configASSERT( pxFile != NULL ); - - for( x = 0; x < 1000; x++ ) - { - configASSERT( ff_fputc( 0xff, pxFile ) == 0xff ); - } - - /* Extend the file to 2000 bytes using ff_truncate(). */ - ff_fclose( pxFile ); - pxFile = ff_truncate( pcTestFileName, 2000L ); - configASSERT( pxFile ); - - /* Ensure the file is indeed 2000 bytes long. */ - ff_fclose( pxFile ); - ff_stat( pcTestFileName, &xStat ); - configASSERT( xStat.st_size == 2000L ); - - /* Now the first 1000 bytes should be 0xff, and the second 1000 bytes should - be 0x00. */ - pxFile = ff_fopen( pcTestFileName, "r+" ); - configASSERT( pxFile ); - configASSERT( ff_ftell( pxFile ) == 0 ); - - for( x = 0; x < 1000; x++ ) - { - cChar = ff_fgetc( pxFile ); - configASSERT( cChar == 0xff ); - } - - for( x = 0; x < 1000; x++ ) - { - cChar = ff_fgetc( pxFile ); - configASSERT( cChar == 0x00 ); - } - - /* Use ff_fseek() then ff_seteof() to make the file 1750 bytes long. */ - configASSERT( ff_fseek( pxFile, 1750L, FF_SEEK_SET ) == pdFREERTOS_ERRNO_NONE ); - configASSERT( ff_ftell( pxFile ) == 1750 ); - configASSERT( ff_seteof( pxFile ) == pdFREERTOS_ERRNO_NONE ); - - /* Attempting another read should result in EOF. */ - configASSERT( ff_feof( pxFile ) != 0 ); - configASSERT( ff_fgetc( pxFile ) == FF_EOF ); - - /* This time use truncate to make the file shorter by another 250 bytes. */ - ff_fclose( pxFile ); - ff_stat( pcTestFileName, &xStat ); - configASSERT( xStat.st_size == 1750L ); - pxFile = ff_truncate( pcTestFileName, 1500L ); - - /* Ensure the file is indeed 1500 bytes long. */ - ff_fclose( pxFile ); - ff_stat( pcTestFileName, &xStat ); - configASSERT( xStat.st_size == 1500L ); - - /* Now the first 1000 bytes should be 0xff, and the second 500 bytes should - be 0x00. */ - pxFile = ff_fopen( pcTestFileName, "r" ); - configASSERT( pxFile ); - configASSERT( ff_ftell( pxFile ) == 0 ); - - for( x = 0; x < 1000; x++ ) - { - cChar = ff_fgetc( pxFile ); - configASSERT( cChar == 0xff ); - } - - for( x = 0; x < 500; x++ ) - { - cChar = ff_fgetc( pxFile ); - configASSERT( cChar == 0x00 ); - } - - /* Attempting another read should result in EOF. */ - configASSERT( ff_feof( pxFile ) != 0 ); - configASSERT( ff_fgetc( pxFile ) == FF_EOF ); - - /* Now truncate the file to 0. */ - ff_fclose( pxFile ); - pxFile = ff_truncate( pcTestFileName, 0L ); - configASSERT( pxFile ); - - /* Don't expect to be able to delete an open file. */ - configASSERT( ff_remove( pcTestFileName ) == -1 ); - - /* Ensure the file is indeed 0 bytes long. */ - ff_fclose( pxFile ); - ff_stat( pcTestFileName, &xStat ); - configASSERT( xStat.st_size == 0L ); - - /* Do expect to be able to delete the file after it is closed. */ - configASSERT( ff_remove( pcTestFileName ) == 0 ); -} -/*-----------------------------------------------------------*/ - -static void prvAlignmentReadWriteTests( const char *pcMountPath ) -{ - TRACE_PRINTF("%s(pcMountPath=%s)\n", __FUNCTION__, pcMountPath); - -const char cOverflowCheckByte = 0xc5; -const size_t xSizeIncrement = 37U; -const size_t xSectorSize = 512U; -const size_t xNumSectors = 3U; -const size_t xOverwriteCheckBytes = 1U; -const size_t xBufferSize = ( xSectorSize * xNumSectors ) + xSizeIncrement; -size_t x, xSkippedBytes, x32BitValues; -char *pcBuffer; -uint32_t *pulVerifyBuffer; -uint32_t *pulVerifyValues; -FF_FILE *pxFile; -FF_Stat_t xStat; -const char* pcTestFileName = "test.bin"; -int iReturned, iExpectedReturn; - - /* Start in the root of the mounted disk. */ - ff_chdir( pcMountPath ); - - /* Create an array that will hold 3 whole sectors plus a few additional - bytes, plus a byte at the end which is used to check it does not get - overwritten. */ - pcBuffer = ( char * ) pvPortMalloc( xBufferSize + xOverwriteCheckBytes ); - configASSERT( pcBuffer ); - pulVerifyBuffer = ( uint32_t * ) pvPortMalloc( xBufferSize ); - - /* Write a byte to the end of the buffer which is used to ensure nothing has - ever written off the end of the buffer. */ - pcBuffer[ xBufferSize ] = cOverflowCheckByte; - - /* In case this test has been executed on the disk already - ensure the file - does not exist. */ - ff_remove( pcTestFileName ); - - /* Create a file that will hold the entire buffer. */ - pxFile = ff_truncate( pcTestFileName, xBufferSize ); - - /* Check the file has the expected size. */ - ff_fclose( pxFile ); - ff_stat( pcTestFileName, &xStat ); - configASSERT( xStat.st_size == xBufferSize ); - - /* Check the file was filled with zeros by reading it back into a buffer - that was previously set to ff. */ - pxFile = ff_fopen( pcTestFileName, "r" ); - configASSERT( pxFile ); - - memset( pcBuffer, 0xff, xBufferSize ); - - /* The +1 is to ensure the xSizeIncrement bytes are also read. */ - iReturned = ff_fread( pcBuffer, xSectorSize, xNumSectors + 1U, pxFile ); - - /* Expected to have read xNumSectors worth of xSectorSize, but xBufferSize - bytes. */ - configASSERT( iReturned == ( int ) xNumSectors ); - - /* Check the buffer is now full of zeros. */ - for( x = 0; x < xBufferSize; x++ ) - { - configASSERT( pcBuffer[ x ] == 0x00 ); - } - - /* Check the byte at the end of the buffer was not overwritten. */ - configASSERT( pcBuffer[ xBufferSize ] == cOverflowCheckByte ); - - /* Re-open in append mode, the move the write position to the start of the - file. */ - ff_fclose( pxFile ); - pxFile = ff_fopen( pcTestFileName, "r+" ); - configASSERT( pxFile ); - iReturned = ( int ) ff_ftell( pxFile ); - configASSERT( iReturned == 0 ); /*_RB_ Unexpected, but how the GCC one works. */ - - /* Fill the file with incrementing 32-bit number starting from various - different offset. */ - for( xSkippedBytes = 0; xSkippedBytes < xSizeIncrement; xSkippedBytes++ ) - { - /* The buffer is going to be written to from xSkippedBytes bytes in. - When that is done, how many 32-bit integers will it hold. */ - x32BitValues = ( xBufferSize - xSkippedBytes ) / sizeof( uint32_t ); - - /* This time start xSkippedBytes bytes into the file. */ - ff_fseek( pxFile, xSkippedBytes, FF_SEEK_SET ); - iReturned = ( int ) ff_ftell( pxFile ); - configASSERT( iReturned == ( int ) xSkippedBytes ); - iExpectedReturn = xSkippedBytes; - - memset( pulVerifyBuffer, 0x00, xBufferSize ); - pulVerifyValues = ( uint32_t * ) pulVerifyBuffer; - - for( x = 0; x < x32BitValues; x++ ) - { - iReturned = ff_fwrite( &x, sizeof( x ), 1, pxFile ); - configASSERT( iReturned == 1 ); - - /* Also write the value into the verify buffer for easy checking - when the file is read back. pulVerifyBuffer should remain on a - 4 byte boundary as it starts from index 0. */ - pulVerifyValues[ x ] = x; - - iExpectedReturn += sizeof( x ); - iReturned = ( int ) ff_ftell( pxFile ); - configASSERT( iExpectedReturn == iReturned ); - } - - /* Calculate the expected file position. */ - iExpectedReturn = ( x32BitValues * sizeof( uint32_t ) ) + xSkippedBytes; - - /* Check the expected file position. */ - iReturned = ff_ftell( pxFile ); - configASSERT( iReturned == iExpectedReturn ); - - /* Read the entire file back into a buffer to check its contents. */ - ff_fseek( pxFile, 0, FF_SEEK_SET ); - memset( pcBuffer, 0x00, xBufferSize ); - iReturned = ff_fread( pcBuffer, iExpectedReturn, 1, pxFile ); - - /* The whole file was read back in one. */ - configASSERT( iReturned == 1 ); - - /* Verify the data. The first xSkippedBytes bytes of the buffer should - still be zero. */ - for( x = 0; x < xSkippedBytes; x++ ) - { - configASSERT( pcBuffer[ x ] == 0 ); - } - - /* As just verified, the first xSkippedBytes bytes were skipped so the - first xSkippedBytes bytes in pcBuffer are zero, pulVerifyBuffer was - written to from its start, and the number of bytes written was the total - number of uint_32 variables that would fit in the buffer. */ - configASSERT( memcmp( ( void * ) ( pcBuffer + xSkippedBytes ), ( void * ) pulVerifyBuffer, ( x32BitValues * sizeof( uint32_t ) ) ) == 0 ); - - - /* Read the file back one byte at a time to check its contents. */ - memset( pcBuffer, 0xff, xBufferSize ); - ff_fseek( pxFile, 0, FF_SEEK_SET ); - for( x = 0; x < ( size_t ) iExpectedReturn; x++ ) - { - iReturned = ff_fread( &( pcBuffer[ x ] ), sizeof( char ), 1, pxFile ); - configASSERT( iReturned == sizeof( char ) ); - iReturned = ff_ftell( pxFile ); - configASSERT( iReturned == ( long ) ( x + 1U ) ); - } - - /* Verify the data using the same offsets as the previous time. */ - configASSERT( memcmp( ( void * ) ( pcBuffer + xSkippedBytes ), ( void * ) pulVerifyBuffer, ( x32BitValues * sizeof( uint32_t ) ) ) == 0 ); - - /* Read the file back three bytes at a time to check its contents. */ - memset( pcBuffer, 0xff, xBufferSize ); - ff_fseek( pxFile, 0, FF_SEEK_SET ); - for( x = 0; x < ( size_t ) iExpectedReturn; x += 3 ) - { - iReturned = ff_fread( &( pcBuffer[ x ] ), 1, 3, pxFile ); - - /* 3 does not go into 4. Don't assert check the last iteration as - it won't be an exact multiple. */ - if( x < ( iExpectedReturn - sizeof( uint32_t ) ) ) - { - configASSERT( iReturned == 3 ); - iReturned = ff_ftell( pxFile ); - configASSERT( iReturned == ( long ) ( x + 3 ) ); - } - } - - /* Verify the data. */ - configASSERT( memcmp( ( void * ) ( pcBuffer + xSkippedBytes ), ( void * ) pulVerifyBuffer, ( x32BitValues * sizeof( uint32_t ) ) ) == 0 ); - } - - ff_fclose( pxFile ); - - /* Check the byte at the end of the buffer was not overwritten. */ - configASSERT( pcBuffer[ xBufferSize ] == cOverflowCheckByte ); - - vPortFree( pcBuffer ); - vPortFree( pulVerifyBuffer ); -} -/*-----------------------------------------------------------*/ - -static void prvTest_ff_rename( const char *pcMountPath ) -{ - TRACE_PRINTF("%s(pcMountPath=%s)\n", __FUNCTION__, pcMountPath); - -FF_FILE *pxFile; -int iReturned; -const char *pcStringToWrite = "This string is written to the file\n"; -const char *pcSecondStringToWrite = "This is another string written to a file\n"; -char cReadBuffer[ 45 ]; - - /* cReadBuffer must be at least big enough to hold pcStringToWrite plus a - null terminator. */ - configASSERT( sizeof( cReadBuffer ) >= ( strlen( pcSecondStringToWrite ) + 1 ) ); - - /* Move to the root of the mount. */ - iReturned = ff_chdir( pcMountPath ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - /* Attempt to move a file that does not exist. */ - iReturned = ff_rename( "file1.bin", "file2.bin", pdFALSE ); - configASSERT( iReturned == -1 ); - - /* Create subdirectories into/from which files will be moved. */ - iReturned = ff_mkdir( "source_dir" ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - iReturned = ff_mkdir( "destination_dir" ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - - /* Create a file in source_dir then write some data to it. */ - pxFile = ff_fopen( "source_dir/source.txt", "w" ); - configASSERT( pxFile != NULL ); - ff_fwrite( pcStringToWrite, strlen( pcStringToWrite ), 1, pxFile ); - - /* Calling ff_filelength() should fail as the file is not read only. */ - /* configASSERT( ff_filelength( pxFile ) == 0 ); _RB_ The behavior of this function has changed, the documentation and or the test will be updated */ - - /* Ensure the file exists by closing it, reopening it, and reading the - string back. */ - iReturned = ff_fclose( pxFile ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - ff_chdir( "source_dir" ); - pxFile = ff_fopen( "source.txt", "r" ); - configASSERT( pxFile != NULL ); - memset( cReadBuffer, 0x00, sizeof( cReadBuffer ) ); - ff_fgets( cReadBuffer, sizeof( cReadBuffer ), pxFile ); - configASSERT( strcmp( cReadBuffer, pcStringToWrite ) == 0 ); - - /* Calling ff_filelength() should not fail as the file is open for - reading. */ - configASSERT( ff_filelength( pxFile ) == strlen( pcStringToWrite ) ); - - /* Should not be able to move the file because it is open. */ - iReturned = ff_rename( "source.txt", "../destination_dir/destination.txt", pdFALSE ); - configASSERT( iReturned == -1 ); - - /* Close the file so it can be moved. */ - ff_fclose( pxFile ); - - iReturned = ff_rename( "source.txt", "../destination_dir/destination.txt", pdFALSE ); - if (iReturned != pdFREERTOS_ERRNO_NONE) { - FF_PRINTF("ff_rename error: %s (%d)\n", strerror(errno), errno); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - } - - /* Attempt to open the file - it should no longer exist. */ - pxFile = ff_fopen( "source.txt", "r" ); - configASSERT( pxFile == NULL ); - - /* Create a new file to try and copy it over an existing file. */ - pxFile = ff_fopen( "source.txt2", "w" ); - configASSERT( pxFile != NULL ); - - /* Write different data to the file. */ - iReturned = ff_fwrite( pcSecondStringToWrite, 1, strlen( pcSecondStringToWrite ), pxFile ); - configASSERT( iReturned == ( int ) strlen( pcSecondStringToWrite ) ); - - /* Now close the file and try moving it to the file that already exists. - That should fail if the last parameter is pdFALSE. */ - ff_fclose( pxFile ); - iReturned = ff_rename( "source.txt2", "../destination_dir/destination.txt", pdFALSE ); - configASSERT( iReturned == -1 ); - - /* This time the last parameter is pdTRUE, so the file should be moved even - through the destination already existed. */ - iReturned = ff_rename( "source.txt2", "../destination_dir/destination.txt", pdTRUE ); - configASSERT( iReturned == 0 ); - - /* Now open the destination file and ensure it was copied as expected. */ - iReturned = ff_chdir( "../destination_dir" ); - configASSERT( iReturned == pdFREERTOS_ERRNO_NONE ); - pxFile = ff_fopen( "destination.txt", "r" ); - configASSERT( pxFile != NULL ); - configASSERT( ff_filelength( pxFile ) == strlen( pcSecondStringToWrite ) ); - memset( cReadBuffer, 0x00, sizeof( cReadBuffer ) ); - /* +1 to get the \n on the end of the string too. */ - //ff_fgets( cReadBuffer, strlen( pcSecondStringToWrite ) + 1, pxFile ); - ff_fgets( cReadBuffer, strlen( pcSecondStringToWrite ) + 4, pxFile ); // extra for utf-8 encoding - configASSERT( strcmp( cReadBuffer, pcSecondStringToWrite ) == 0 ); - - ff_fclose( pxFile ); -} -/*-----------------------------------------------------------*/ - -static void prvTest_ff_fopen( const char *pcMountPath ) -{ - TRACE_PRINTF("%s(pcMountPath=%s)\n", __FUNCTION__, pcMountPath); - -FF_FILE *pxFile; -FF_Stat_t xStat; -size_t xReturned, xByte; -const size_t xBytesToWrite = 10U; -char *pcRAMBuffer, *pcFileName; - - /* Allocate buffers used to hold date written to/from the disk, and the - file names. */ - pcRAMBuffer = ( char * ) pvPortMalloc( fsRAM_BUFFER_SIZE ); - pcFileName = ( char * ) pvPortMalloc( ffconfigMAX_FILENAME ); - configASSERT( pcRAMBuffer ); - configASSERT( pcFileName ); - - /* Generate file name. */ - snprintf( pcFileName, ffconfigMAX_FILENAME, "%s/Dummy.txt", pcMountPath ); - - /* Attempt to open a file that does not exist in read only mode. */ - pxFile = ff_fopen( pcFileName, "r" ); - - /* Do not expect the file to have been opened as it does not exist. */ - configASSERT( pxFile == NULL ); - - /* Attempt to open the same file, this time using a "+" in addition to the - "r". */ - pxFile = ff_fopen( pcFileName, "r+" ); - - /* The file still does not exist. */ - configASSERT( pxFile == NULL ); - - /* This time attempt to open the file in read/write mode. */ - pxFile = ff_fopen( pcFileName, "w" ); - - /* The file should have been created. */ - configASSERT( pxFile != NULL ); - - /* Write some ascii '0's to the file. */ - memset( pcRAMBuffer, ( int ) '0', fsRAM_BUFFER_SIZE ); - xReturned = ff_fwrite( pcRAMBuffer, xBytesToWrite, 1, pxFile ); - - /* One item was written. */ - configASSERT( xReturned == 1 ); - - /* The write position should be xBytesToWrite into the file. */ - configASSERT( ff_ftell( pxFile ) == ( long ) xBytesToWrite ); - - /* The file length as reported by ff_stat() should be zero though as the - file has not yet been committed. */ - ff_stat( pcFileName, &xStat ); - configASSERT( xStat.st_size == 0 ); - - /* Close the file so it can be re-opened in append mode. */ - ff_fclose( pxFile ); - - /* Now the file has been closed its size should be reported. */ - ff_stat( pcFileName, &xStat ); - configASSERT( xStat.st_size == xBytesToWrite ); - - pxFile = ff_fopen( pcFileName, "a" ); - configASSERT( pxFile ); - - /* Write some ascii '1's to the file. */ - memset( pcRAMBuffer, ( int ) '1', fsRAM_BUFFER_SIZE ); - xReturned = ff_fwrite( pcRAMBuffer, 1, xBytesToWrite, pxFile ); - configASSERT( xReturned == xBytesToWrite ); - - /* The size reported by stat should not yet have changed. */ - ff_stat( pcFileName, &xStat ); - configASSERT( xStat.st_size == xBytesToWrite ); - - /* The file should contain xBytesToWrite lots of '0' and xBytesToWrite lots - of '1'. The file was opened in append mode so the '1's should appear after - the '0's. Open the file in read mode to check the bytes appear in the file - as expected. */ - ff_fclose( pxFile ); - - /* Now the size reported by ff_stat() should have changed. */ - ff_stat( pcFileName, &xStat ); - configASSERT( xStat.st_size == ( xBytesToWrite * 2UL ) ); - - pxFile = ff_fopen( pcFileName, "r" ); - configASSERT( pxFile != NULL ); - - /* Start with the RAM buffer clear. */ - memset( pcRAMBuffer, 0x00, fsRAM_BUFFER_SIZE ); - - /* Read the data into the RAM buffer. */ - ff_fread( pcRAMBuffer, ( 2 * xBytesToWrite ), 1, pxFile ); - - /* Check each byte is as expected. */ - for( xByte = 0; xByte < ( 2 * xBytesToWrite ); xByte++ ) - { - if( xByte < xBytesToWrite ) - { - configASSERT( pcRAMBuffer[ xByte ] == '0' ); - } - else - { - configASSERT( pcRAMBuffer[ xByte ] == '1' ); - } - } - - /* It should not be possible to write to the file as it was opened read - only. */ - xReturned = ff_fwrite( pcRAMBuffer, 1, 1, pxFile ); - configASSERT( xReturned == 0 ); - - /* File size should not have changed. */ - ff_fclose( pxFile ); - ff_stat( pcFileName, &xStat ); - configASSERT( xStat.st_size == ( xBytesToWrite * 2UL ) ); - - /* The file now contains data. Re-open it using "w" mode again. It should - be truncated to zero. */ - pxFile = ff_fopen( pcFileName, "w" ); - ff_fclose( pxFile ); - ff_stat( pcFileName, &xStat ); - configASSERT( xStat.st_size == 0 ); - - vPortFree( pcRAMBuffer ); - vPortFree( pcFileName ); -} -/*-----------------------------------------------------------*/ diff --git a/examples/command_line/tests/simple.c b/examples/command_line/tests/simple.c deleted file mode 100644 index 0cd1058..0000000 --- a/examples/command_line/tests/simple.c +++ /dev/null @@ -1,154 +0,0 @@ -/* simple.c -Copyright 2021 Carl John Kugler III - -Licensed under the Apache License, Version 2.0 (the License); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at - - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software distributed -under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR -CONDITIONS OF ANY KIND, either express or implied. See the License for the -specific language governing permissions and limitations under the License. -*/ -// Adapted from "FATFileSystem example" -// at https://os.mbed.com/docs/mbed-os/v5.15/apis/fatfilesystem.html - -#include -#include -#include -// -#include "f_util.h" -#include "ff.h" - -// Maximum number of elements in buffer -#define BUFFER_MAX_LEN 10 - -#define TRACE_PRINTF(fmt, args...) -//#define TRACE_PRINTF printf - -extern void ls(const char *dir); - -void simple() { - printf("\nSimple Test\n"); - - char cwdbuf[FF_LFN_BUF - 12] = {0}; - FRESULT fr = f_getcwd(cwdbuf, sizeof cwdbuf); - if (FR_OK != fr) { - printf("f_getcwd error: %s (%d)\n", FRESULT_str(fr), fr); - return; - } - // Open the numbers file - printf("Opening \"numbers.txt\"... "); - FIL f; - fr = f_open(&f, "numbers.txt", FA_READ | FA_WRITE); - printf("%s\n", (FR_OK != fr ? "Fail :(" : "OK")); - fflush(stdout); - if (FR_OK != fr && FR_NO_FILE != fr) { - printf("f_open error: %s (%d)\n", FRESULT_str(fr), fr); - return; - } else if (FR_NO_FILE == fr) { - // Create the numbers file if it doesn't exist - printf("No file found, creating a new file... "); - fflush(stdout); - fr = f_open(&f, "numbers.txt", FA_CREATE_ALWAYS | FA_WRITE | FA_READ); - printf("%s\n", (FR_OK != fr ? "Fail :(" : "OK")); - if (FR_OK != fr) printf("f_open error: %s (%d)\n", FRESULT_str(fr), fr); - fflush(stdout); - for (int i = 0; i < 10; i++) { - printf("\rWriting numbers (%d/%d)... ", i, 10); - fflush(stdout); - // When the string was written successfuly, it returns number of - // character encoding units written to the file. When the function - // failed due to disk full or any error, a negative value will be - // returned. - int rc = f_printf(&f, " %d\n", i); - if (rc < 0) { - printf("Fail :(\n"); - printf("f_printf error: %s (%d)\n", FRESULT_str(fr), fr); - } - } - printf("\rWriting numbers (%d/%d)... OK\n", 10, 10); - fflush(stdout); - - printf("Seeking file... "); - fr = f_lseek(&f, 0); - printf("%s\n", (FR_OK != fr ? "Fail :(" : "OK")); - if (FR_OK != fr) - printf("f_lseek error: %s (%d)\n", FRESULT_str(fr), fr); - fflush(stdout); - } - // Go through and increment the numbers - for (int i = 0; i < 10; i++) { - printf("\nIncrementing numbers (%d/%d)... ", i, 10); - - // Get current stream position - long pos = f_tell(&f); - - // Parse out the number and increment - char buf[BUFFER_MAX_LEN]; - if (!f_gets(buf, BUFFER_MAX_LEN, &f)) { - printf("error: f_gets returned NULL\n"); - } - char *endptr; - int32_t number = strtol(buf, &endptr, 10); - if ((endptr == buf) || // No character was read - (*endptr && *endptr != '\n') // The whole input was not converted - ) { - continue; - } - number += 1; - - // Seek to beginning of number - f_lseek(&f, pos); - - // Store number - f_printf(&f, " %d\n", (int)number); - - // Flush between write and read on same file - f_sync(&f); - } - printf("\rIncrementing numbers (%d/%d)... OK\n", 10, 10); - fflush(stdout); - - // Close the file which also flushes any cached writes - printf("Closing \"numbers.txt\"... "); - fr = f_close(&f); - printf("%s\n", (FR_OK != fr ? "Fail :(" : "OK")); - if (FR_OK != fr) printf("f_close error: %s (%d)\n", FRESULT_str(fr), fr); - fflush(stdout); - - ls(""); - - fr = f_chdir("/"); - if (FR_OK != fr) printf("chdir error: %s (%d)\n", FRESULT_str(fr), fr); - - ls(""); - - // Display the numbers file - char pathbuf[FF_LFN_BUF] = {0}; - snprintf(pathbuf, sizeof pathbuf, "%s/%s", cwdbuf, "numbers.txt"); - printf("Opening \"%s\"... ", pathbuf); - fr = f_open(&f, pathbuf, FA_READ); - printf("%s\n", (FR_OK != fr ? "Fail :(" : "OK")); - if (FR_OK != fr) printf("f_open error: %s (%d)\n", FRESULT_str(fr), fr); - fflush(stdout); - - printf("numbers:\n"); - while (!f_eof(&f)) { - // int c = f_getc(f); - char c; - UINT br; - fr = f_read(&f, &c, sizeof c, &br); - if (FR_OK != fr) - printf("f_read error: %s (%d)\n", FRESULT_str(fr), fr); - else - printf("%c", c); - } - - printf("\nClosing \"%s\"... ", pathbuf); - fr = f_close(&f); - printf("%s\n", (FR_OK != fr ? "Fail :(" : "OK")); - if (FR_OK != fr) printf("f_close error: %s (%d)\n", FRESULT_str(fr), fr); - fflush(stdout); -} diff --git a/examples/dynamic_config/CMakeLists.txt b/examples/dynamic_config/CMakeLists.txt index 19dba8e..21f00b9 100644 --- a/examples/dynamic_config/CMakeLists.txt +++ b/examples/dynamic_config/CMakeLists.txt @@ -24,6 +24,10 @@ add_executable(dynamic_config_example main.cpp ) +# Can leave these off for silent mode: +#add_compile_definitions(USE_PRINTF USE_DBG_PRINTF) +#add_compile_definitions(USE_PRINTF) + pico_set_program_name(dynamic_config_example "dynamic_config_example") pico_set_program_version(dynamic_config_example "0.1") diff --git a/examples/simple/CMakeLists.txt b/examples/simple/CMakeLists.txt index 7a4d712..3833c18 100644 --- a/examples/simple/CMakeLists.txt +++ b/examples/simple/CMakeLists.txt @@ -24,6 +24,9 @@ add_executable(simple_example main.c hw_config.c ) +# Can leave these off for silent mode: +# add_compile_definitions(USE_PRINTF USE_DBG_PRINTF) +add_compile_definitions(USE_PRINTF) # Add the standard library and FatFS/SPI to the build target_link_libraries(simple_example diff --git a/include/FatFsSd.h b/include/FatFsSd.h index 59f756d..43640cb 100755 --- a/include/FatFsSd.h +++ b/include/FatFsSd.h @@ -13,10 +13,6 @@ specific language governing permissions and limitations under the License. */ #pragma once -// #ifdef __cplusplus -// extern "C" { -// #endif - #include "../src/ff15/source/ff.h" // #include "../src/ff15/source/diskio.h" /* Declarations of disk functions */ @@ -26,6 +22,22 @@ specific language governing permissions and limitations under the License. #include "../src/sd_driver/SDIO/rp2040_sdio.h" #include "../src/sd_driver/SPI/spi.h" -// #ifdef __cplusplus -// } -// #endif +#ifdef __cplusplus + +class FatFsSpi { + +}; +class FatFsSdCard { + sd_card_t sd_card = {}; +public: + FatFsSdCard() = delete; + FatFsSdCard(const char *name); +}; +class FatFsSdCardSpi: public FatFsSdCard { + +}; +class FatFsSdCardSdio: public FatFsSdCard { + +}; + +#endif // __cplusplus \ No newline at end of file diff --git a/library.json b/library.json index 0e5f511..341e568 100755 --- a/library.json +++ b/library.json @@ -69,7 +69,8 @@ "+", "+", "+", - "+" + "+", + "+" ], "flags": [ "-D _GNU_SOURCE", diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 90df933..69f2dce 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,7 +20,7 @@ target_sources(FatFs_SPI INTERFACE target_include_directories(FatFs_SPI INTERFACE ff15/source sd_driver - SdFat + tests include ) target_link_libraries(FatFs_SPI INTERFACE diff --git a/src/ff15/documents/res/app4.c b/src/ff15/documents/res/app4.c index c46d1a0..ec88959 100755 --- a/src/ff15/documents/res/app4.c +++ b/src/ff15/documents/res/app4.c @@ -4,8 +4,8 @@ / WARNING: The data on the target drive will be lost! */ -#include #include +#include "my_debug.h" #include "ff.h" /* Declarations of sector size */ #include "diskio.h" /* Declarations of disk functions */ diff --git a/src/glue.c b/src/glue.c index c9e011e..1fb775a 100644 --- a/src/glue.c +++ b/src/glue.c @@ -19,7 +19,6 @@ specific language governing permissions and limitations under the License. /* This is an example of glue functions to attach various exsisting */ /* storage control modules to the FatFs module with a defined API. */ /*-----------------------------------------------------------------------*/ -#include // #include "ff.h" /* Obtains integer types */ // diff --git a/src/include/my_debug.h b/src/include/my_debug.h index 42455df..ea8d258 100755 --- a/src/include/my_debug.h +++ b/src/include/my_debug.h @@ -13,7 +13,13 @@ specific language governing permissions and limitations under the License. */ #pragma once -#include +#ifdef USE_PRINTF +# include +#else +# define printf(...) // Do nothing +# define puts(...) +# define fflush(...) +#endif #ifdef __cplusplus extern "C" { @@ -31,8 +37,12 @@ extern "C" { //#if defined(DEBUG) && !defined(NDEBUG) // #define DBG_PRINTF my_printf //#else -#define DBG_PRINTF(fmt, args...) {} /* Don't do anything in release builds*/ -//#endif + +#if defined(USE_DBG_PRINTF) +# define DBG_PRINTF my_printf +#else +# define DBG_PRINTF(fmt, args...) {} /* Don't do anything in release builds*/ +#endif #define myASSERT(__e) \ { ((__e) ? (void)0 : my_assert_func(__FILE__, __LINE__, __func__, #__e)); } diff --git a/src/include/util.h b/src/include/util.h index 885a8c1..83a21b3 100755 --- a/src/include/util.h +++ b/src/include/util.h @@ -18,6 +18,7 @@ specific language governing permissions and limitations under the License. #include #include "hardware/structs/scb.h" #include "RP2040.h" +#include "my_debug.h" // works with negative index static inline int wrap_ix(int index, int n) @@ -47,8 +48,9 @@ static inline void dump_bytes(size_t num, uint8_t bytes[num]) { printf("%02hhx", j); if (j < 15) printf(" "); - else + else { printf("\n"); + } } for (size_t i = 0; i < num; i += 16) { printf("%04x ", i); @@ -56,8 +58,9 @@ static inline void dump_bytes(size_t num, uint8_t bytes[num]) { printf("%02hhx", bytes[i + j]); if (j < 15) printf(" "); - else + else { printf("\n"); + } } } printf("\n"); diff --git a/src/my_debug.c b/src/my_debug.c index 1d86046..319d29c 100644 --- a/src/my_debug.c +++ b/src/my_debug.c @@ -11,10 +11,11 @@ under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -#include #include #include "my_debug.h" +#ifdef USE_PRINTF +# include void my_printf(const char *pcFormat, ...) { char pcBuffer[256] = {0}; va_list xArgs; @@ -24,6 +25,12 @@ void my_printf(const char *pcFormat, ...) { printf("%s", pcBuffer); fflush(stdout); } +#else +# define my_printf(...) // Do nothing +# define printf(...) // Do nothing +# define puts(...) +# define fflush(...) +#endif void my_assert_func(const char *file, int line, const char *func, diff --git a/src/rtc.c b/src/rtc.c index 32b9aa5..94ccfa8 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -11,7 +11,6 @@ under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -#include #include // #include "hardware/rtc.h" diff --git a/src/sd_driver/SDIO/rp2040_sdio.c b/src/sd_driver/SDIO/rp2040_sdio.c index 89a0c4a..d841bd2 100755 --- a/src/sd_driver/SDIO/rp2040_sdio.c +++ b/src/sd_driver/SDIO/rp2040_sdio.c @@ -8,19 +8,19 @@ // https://www.sdcard.org/downloads/pls/ // "SDIO Physical Layer Simplified Specification Version 8.00" -#include "rp2040_sdio.h" -#include "rp2040_sdio.pio.h" -#include +#include +// #include #include -// #include "ZuluSCSI_platform.h" -// #include "ZuluSCSI_log.h" +#include +// +#include "hw_config.h" +#include "my_debug.h" +#include "rp2040_sdio.h" +#include "rp2040_sdio.pio.h" #include "RP2040.h" -#include -#include #include "sd_card.h" #include "util.h" -#include "hw_config.h" // #define azdbg(Params...)DMA_CH // #define azlog(Params...) diff --git a/src/sd_driver/SDIO/sd_card_sdio.c b/src/sd_driver/SDIO/sd_card_sdio.c index 743628e..a44fa93 100755 --- a/src/sd_driver/SDIO/sd_card_sdio.c +++ b/src/sd_driver/SDIO/sd_card_sdio.c @@ -4,17 +4,18 @@ #ifdef SD_USE_SDIO -#include "rp2040_sdio.h" -#include -#include "SdioCard.h" #include -#include -#include #include - +#include +// +#include +// #include "diskio.h" -#include "util.h" +#include "my_debug.h" +#include "rp2040_sdio.h" #include "rp2040_sdio.pio.h" +#include "SdioCard.h" +#include "util.h" // #define azlog(...) // #define azdbg(...) diff --git a/src/sd_driver/SPI/sd_spi.c b/src/sd_driver/SPI/sd_spi.c index c1450af..434639d 100755 --- a/src/sd_driver/SPI/sd_spi.c +++ b/src/sd_driver/SPI/sd_spi.c @@ -15,7 +15,6 @@ specific language governing permissions and limitations under the License. /* Standard includes. */ #include #include -#include #include // #include "hardware/gpio.h"