diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 03f5ff0..590e97c 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -22,7 +22,9 @@ jobs: - STMicroelectronics:stm32:Nucleo_144:pnum=NUCLEO_F207ZG - STMicroelectronics:stm32:GenF4:pnum=FEATHER_F405 - STMicroelectronics:stm32:Disco:pnum=DISCO_F746NG + - STMicroelectronics:stm32:Disco:pnum=STM32H573I_DK - STMicroelectronics:stm32:GenH7:pnum=DAISY_PATCH_SM + - STMicroelectronics:stm32:GenL1:pnum=GENERIC_L151ZDTX - STMicroelectronics:stm32:Eval:pnum=STEVAL_MKSBOX1V1,usb=CDCgen - STMicroelectronics:stm32:Nucleo_144:pnum=NUCLEO_L552ZE_Q - STMicroelectronics:stm32:Nucleo_144:pnum=NUCLEO_U575ZI_Q @@ -37,4 +39,4 @@ jobs: libraries: | # Install the library from the local path. - source-path: ./ - - name: FatFS \ No newline at end of file + - name: FatFS diff --git a/.gitignore b/.gitignore index 1377554..21d3202 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ *.swp +.vscode +astyle.out diff --git a/README.md b/README.md index 338ab84..7e3059b 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,9 @@ Some default definitions can be overridden using: #### SDIO/SDMMC pins definition -Since STM32 core v2.6.0, the `PinMap_SD[]` array defined in the `PeripheralPins*.c` has been split per signals: +> [!IMPORTANT] +> Since STM32 core v2.6.0, the `PinMap_SD[]` array defined in the `PeripheralPins*.c` has been split per signals: + ```C PinMap_SD_CK[] PinMap_SD_DATA0[] @@ -74,9 +76,11 @@ By default, if no pins are explicitly defined, the first one from each array is * `SDX_D0DIR` * `SDX_D123DIR` -* or redefine the default one before call of `begin()` of `SDClass` or `init()` of `Sd2Card`, use the following methods: +* or redefine the default one before call of `begin()` of `SDClass` or `init()` of `Sd2Card`, using the following methods: * `setDx(uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3)` + > [!NOTE] + > If `SD_BUS_WIDE_1B` is used only `data0` is needed. * `setCK(uint32_t ck)` * `setCK(PinName ck)` * `setCMD(uint32_t cmd)` @@ -106,31 +110,6 @@ By default, if no pins are explicitly defined, the first one from each array is SD.begin(); ``` -* or using the `begin()` of `SDClass` or `init()` of `Sd2Card` methods: - - * For `SDIO`: - * `SDClass`: - * `begin(uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3, uint32_t ck, uint32_t cmd)` - * `begin(uint32_t detect = SD_DETECT_NONE, uint32_t data0 = SDX_D0, uint32_t data1 = SDX_D1, uint32_t data2 = SDX_D2, uint32_t data3 = SDX_D3, uint32_t ck = SDX_CK, uint32_t cmd = SDX_CMD, uint32_t ckin = SDX_CKIN, uint32_t cdir = SDX_CDIR, uint32_t d0dir = SDX_D0DIR, uint32_t d123dir = SDX_D123DIR);` - * `Sd2Card`: - * `init(uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3, uint32_t ck, uint32_t cmd)` - * `init(uint32_t detect = SD_DETECT_NONE, uint32_t data0 = SDX_D0, uint32_t data1 = SDX_D1, uint32_t data2 = SDX_D2, uint32_t data3 = SDX_D3, uint32_t ck = SDX_CK, uint32_t cmd = SDX_CMD);` - - * For `SDMMC`: - * `SDClass`: - * `begin(uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3, uint32_t ck, uint32_t cmd, uint32_t ckin, uint32_t cdir, uint32_t d0dir, uint32_t d123dir);` - * `begin(uint32_t detect = SD_DETECT_NONE, uint32_t data0 = SDX_D0, uint32_t data1 = SDX_D1, uint32_t data2 = SDX_D2, uint32_t data3 = SDX_D3, uint32_t ck = SDX_CK, uint32_t cmd = SDX_CMD, uint32_t ckin = SDX_CKIN, uint32_t cdir = SDX_CDIR, uint32_t d0dir = SDX_D0DIR, uint32_t d123dir = SDX_D123DIR);` - * - * * `Sd2Card`: - * `init(uint32_t data0 = SDX_D0, uint32_t data1 = SDX_D1, uint32_t data2 = SDX_D2, uint32_t data3 = SDX_D3, uint32_t ck = SDX_CK, uint32_t cmd = SDX_CMD, uint32_t ckin = SDX_CKIN, uint32_t cdir = SDX_CDIR, uint32_t d0dir = SDX_D0DIR, uint32_t d123dir = SDX_D123DIR)` - * `init(uint32_t detect = SD_DETECT_NONE, uint32_t data0 = SDX_D0, uint32_t data1 = SDX_D1, uint32_t data2 = SDX_D2, uint32_t data3 = SDX_D3, uint32_t ck = SDX_CK, uint32_t cmd = SDX_CMD, uint32_t ckin = SDX_CKIN, uint32_t cdir = SDX_CDIR, uint32_t d0dir = SDX_D0DIR, uint32_t d123dir = SDX_D123DIR);` - - *Code snippet:* -```C++ - card.init(PE12, PE13, PE14, PE15, PB14, PB15); - SD.begin(SD_DETECT_PIN, PE12, PE13, PE14, PE15, PB14, PB15); -``` - #### SD configurations * `SD_INSTANCE`: some STM32 can have 2 SD peripherals `SDMMC1` and `SDMMC2`, note that this library can managed only one peripheral @@ -144,7 +123,6 @@ By default, if no pins are explicitly defined, the first one from each array is * `SD_BUS_WIDE`: specifies the SDMMC bus width * `SD_BUS_WIDE_1B` * `SD_BUS_WIDE_4B` (default) - * `SD_BUS_WIDE_8B` * `SD_CLK_DIV`: specifies the clock frequency of the SDMMC controller (0-255) * `SDIO_TRANSFER_CLK_DIV` (default) for `SDIO` @@ -161,5 +139,5 @@ By default, if no pins are explicitly defined, the first one from each array is #### SD detect and timeout * `SD_DETECT_PIN` pin number - +* `SD_DETECT_LEVEL` default `LOW` * `SD_DATATIMEOUT` constant for Read/Write block diff --git a/examples/CardInfo/CardInfo.ino b/examples/CardInfo/CardInfo.ino index 02c210b..cdc8e4d 100644 --- a/examples/CardInfo/CardInfo.ino +++ b/examples/CardInfo/CardInfo.ino @@ -20,15 +20,15 @@ Sd2Card card; SdFatFs fatFs; -void setup() -{ +void setup() { bool disp = false; // Open serial communications and wait for port to open: Serial.begin(9600); - while (!Serial); + while (!Serial) + ; Serial.print("\nInitializing SD card..."); - while(!card.init(SD_DETECT_PIN)) { + while (!card.init(SD_DETECT_PIN)) { if (!disp) { Serial.println("initialization failed. Is a card inserted?"); disp = true; @@ -66,9 +66,9 @@ void setup() Serial.println(fatFs.fatType(), DEC); Serial.println(); - volumesize = fatFs.blocksPerCluster(); // clusters are collections of blocks - volumesize *= fatFs.clusterCount(); // we'll have a lot of clusters - volumesize *= 512; // SD card blocks are always 512 bytes + volumesize = fatFs.blocksPerCluster(); // clusters are collections of blocks + volumesize *= fatFs.clusterCount(); // we'll have a lot of clusters + volumesize *= 512; // SD card blocks are always 512 bytes Serial.print("Volume size (bytes): "); Serial.println(volumesize); Serial.print("Volume size (Kbytes): "); @@ -85,6 +85,13 @@ void setup() // list all files in the card with date and size root.ls(LS_R | LS_DATE | LS_SIZE); root.close(); + if (!fatFs.deinit()) { + Serial.println("Failed to deinit card"); + } + if (!card.deinit()) { + Serial.println("Failed to deinit card"); + } + Serial.println("###### End of the SD tests ######"); } diff --git a/examples/Datalogger/Datalogger.ino b/examples/Datalogger/Datalogger.ino index 515ce17..7604c2a 100644 --- a/examples/Datalogger/Datalogger.ino +++ b/examples/Datalogger/Datalogger.ino @@ -18,22 +18,20 @@ #define SD_DETECT_PIN SD_DETECT_NONE #endif -uint32_t A[] = { A0, A1, A2}; +uint32_t A[] = { A0, A1, A2 }; File dataFile; -void setup() -{ +void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { - ; // wait for serial port to connect. Needed for Leonardo only + ; // wait for serial port to connect. Needed for Leonardo only } Serial.print("Initializing SD card..."); // see if the card is present and can be initialized: - while (!SD.begin(SD_DETECT_PIN)) - { + while (!SD.begin(SD_DETECT_PIN)) { delay(10); } delay(100); @@ -52,8 +50,7 @@ void setup() } } -void loop() -{ +void loop() { // make a string for assembling the data to log: String dataString = ""; @@ -70,7 +67,7 @@ void loop() // if the file is available, write to it: if (dataFile) { dataFile.println(dataString); - dataFile.flush(); // use flush to ensure the data written + dataFile.flush(); // use flush to ensure the data written // print to the serial port too: Serial.println(dataString); } diff --git a/examples/DumpFile/DumpFile.ino b/examples/DumpFile/DumpFile.ino index 41a755e..2927b65 100644 --- a/examples/DumpFile/DumpFile.ino +++ b/examples/DumpFile/DumpFile.ino @@ -19,19 +19,17 @@ #define SD_DETECT_PIN SD_DETECT_NONE #endif -void setup() -{ +void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { - ; // wait for serial port to connect. Needed for Leonardo only + ; // wait for serial port to connect. Needed for Leonardo only } Serial.print("Initializing SD card..."); // see if the card is present and can be initialized: - while (!SD.begin(SD_DETECT_PIN)) - { + while (!SD.begin(SD_DETECT_PIN)) { delay(10); } delay(100); @@ -52,9 +50,11 @@ void setup() else { Serial.println("error opening datalog.txt"); } + if (!SD.end()) { + Serial.println("Failed to properly end the SD."); + } Serial.println("###### End of the SD tests ######"); } -void loop() -{ +void loop() { } diff --git a/examples/Files/Files.ino b/examples/Files/Files.ino index 73503d8..8413439 100644 --- a/examples/Files/Files.ino +++ b/examples/Files/Files.ino @@ -18,40 +18,37 @@ File myFile; -void setup() -{ +void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { - ; // wait for serial port to connect. Needed for Leonardo only + ; // wait for serial port to connect. Needed for Leonardo only } Serial.print("Initializing SD card..."); - while (!SD.begin(SD_DETECT_PIN)) - { + while (!SD.begin(SD_DETECT_PIN)) { delay(10); } Serial.println("initialization done."); if (SD.exists("example.txt")) { Serial.println("example.txt exists."); - } - else { + } else { Serial.println("example.txt doesn't exist."); } // open a new file and immediately close it: Serial.println("Creating example.txt..."); + Serial.flush(); myFile = SD.open("example.txt", FILE_WRITE); myFile.close(); // Check to see if the file exists: if (SD.exists("example.txt")) { Serial.println("example.txt exists."); - } - else { + } else { Serial.println("example.txt doesn't exist."); } @@ -61,14 +58,15 @@ void setup() if (SD.exists("example.txt")) { Serial.println("example.txt exists."); - } - else { + } else { Serial.println("example.txt doesn't exist."); } + if (!SD.end()) { + Serial.println("Failed to properly end the SD."); + } Serial.println("###### End of the SD tests ######"); } -void loop() -{ +void loop() { // nothing happens after setup finishes. } diff --git a/examples/Full/Full.ino b/examples/Full/Full.ino index c1baff3..39b7c2c 100644 --- a/examples/Full/Full.ino +++ b/examples/Full/Full.ino @@ -6,244 +6,199 @@ #define SD_DETECT_PIN SD_DETECT_NONE #endif -#define COUNTOF(__BUFFER__) (sizeof(__BUFFER__) / sizeof(*(__BUFFER__))) -#define BUFFERSIZE (COUNTOF(wtext) -1) +#define COUNTOF(__BUFFER__) (sizeof(__BUFFER__) / sizeof(*(__BUFFER__))) +#define BUFFERSIZE (COUNTOF(wtext) - 1) uint32_t file_size = 0, seek_val = false, peek_val = 0; uint32_t byteswritten, bytesread = 0; /* File write buffer */ -uint8_t wtext[] = "This is the Arduino SD Test working with FatFs."; -/* File read buffer */ -uint8_t rtext[BUFFERSIZE]; +const char wtext[] = "This is the Arduino SD Test working with FatFs."; +/* File read buffer including extra "\n\0" */ +char rtext[BUFFERSIZE + 2] = { '\0' }; uint32_t i = 0; bool isdir = false; File MyFile; -void setup() -{ +typedef struct { + const char* tst; + const char* err; + bool res; +} result_t; + + +result_t aResult[] = { + { .tst = "Creating 'STM32' directory...", .err = NULL, .res = false }, + { .tst = "Creating 'ARDUINO' directory...", .err = NULL, .res = false }, + { .tst = "Creating 'ARDUINO/SD' directory...", .err = NULL, .res = false }, + { .tst = "Test bool operator...", .err = "Error MyFile should not be initialized!", .res = false }, + { .tst = "Opening 'STM32/Toremove.txt' file...", .err = "Error to open 'STM32/Toremove.txt' file.", .res = false }, + { .tst = "Opening 'ARDUINO/SD/ARDUINO_SD_TEXT.txt' file...", .err = "Error to open 'ARDUINO/SD/ARDUINO_SD_TEXT.txt' file", .res = false }, + { .tst = " Writing `This is the Arduino SD Test working with FatFs.` into ARDUINO_SD_TEXT.txt file...", .err = NULL, .res = false }, + { .tst = "Opening 'ARDUINO/SD/ARDUINO_SD_TEXT.txt' file...", .err = "Error to open 'ARDUINO/SD/ARDUINO_SD_TEXT.txt' file", .res = false }, + { .tst = " Reading ARDUINO/SD/ARDUINO_SD_TEXT.txt file...", .err = NULL, .res = false }, + { .tst = "Opening 'ARDUINO/SD/TEXT.txt' file...", .err = "Error to open 'ARDUINO/SD/TEXT.txt' file", .res = false }, + { .tst = " Writing and flush `This is the Arduino SD Test working with FatFs.` into ARDUINO/SD/TEXT.txt file...", .err = NULL, .res = false }, + { .tst = "Opening 'ARDUINO/SD/TEXT.txt' file...", .err = "Error to open 'ARDUINO/SD/TEXT.txt' file", .res = false }, + { .tst = " TEXT.txt size:", .err = NULL, .res = false }, + { .tst = " TEXT.txt position value:", .err = NULL, .res = false }, + { .tst = " TEXT.txt seek value over size:", .err = NULL, .res = false }, + { .tst = " TEXT.txt seek value to size:", .err = NULL, .res = false }, + { .tst = " TEXT.txt position value: ", .err = NULL, .res = false }, + { .tst = " TEXT.txt seek value to 0: ", .err = NULL, .res = false }, + { .tst = " TEXT.txt position value: ", .err = NULL, .res = false }, + { .tst = " TEXT.txt peek (10 times): ", .err = NULL, .res = false }, + { .tst = " TEXT.txt content read byte per byte: ", .err = NULL, .res = false }, + { .tst = "Opening 'STM32' dir...", .err = "Error to open 'STM32' dir", .res = false }, + { .tst = "Is 'STM32' is a dir...", .err = NULL, .res = false }, + { .tst = "Opening 'STM32/Toremove.txt' file...", .err = "Error to open 'STM32/Toremove.txt' file", .res = false }, + { .tst = " Is 'STM32/Toremove.txt' is a file: ", .err = NULL, .res = false }, + { .tst = "Removing 'STM32/Toremove.txt' file...", .err = NULL, .res = false }, + { .tst = "Removing 'STM32' dir...", .err = NULL, .res = false }, + { .tst = "Opening 'ARDUINO/SD/PRINT.txt' file...", .err = "Error to open 'ARDUINO/SD/PRINT.txt' file", .res = false }, + { .tst = " Printing to 'ARDUINO/SD/PRINT.txt' file...", .err = NULL, .res = false }, + { .tst = "Opening 'ARDUINO/SD/WRITE.txt' file...", .err = "Error to open 'ARDUINO/SD/WRITE.txt' file", .res = false }, + { .tst = " Writing 'ARDUINO/SD/WRITE.txt' file: ", .err = NULL, .res = false }, + { .tst = "Opening 'ARDUINO/SD/WRITE.txt' file...", .err = "Error to open 'ARDUINO/SD/WRITE.txt' file", .res = false }, + { .tst = " Reading 'ARDUINO/SD/WRITE.txt' file: ", .err = NULL, .res = false }, + { .tst = "Opening 'ARDUINO/SD/WRITE.txt' file...", .err = "Error to open 'ARDUINO/SD/WRITE.txt' file", .res = false }, + { .tst = " Reading 'ARDUINO/SD/WRITE.txt' file: ", .err = NULL, .res = false }, + { .tst = "End SD access...", .err = NULL, .res = false }, +}; + +void setup() { + uint32_t idx = 0; + Serial.begin(9600); - while (!Serial); + while (!Serial) + ; /* Test begin() method */ - while (!SD.begin(SD_DETECT_PIN)) - { + while (!SD.begin(SD_DETECT_PIN)) { delay(10); } delay(100); /* Test mkdir() method */ - Serial.print("Creating 'STM32' directory..."); - if (SD.mkdir("STM32")) { - Serial.println("OK"); - } else { - Serial.println("KO"); - } - Serial.print("Creating 'ARDUINO' directory..."); - if (SD.mkdir("ARDUINO")) { - Serial.println("OK"); - } else { - Serial.println("KO"); - } - Serial.print("Creating 'ARDUINO/SD' directory..."); - if (SD.mkdir("ARDUINO/SD")) { - Serial.println("OK"); - } else { - Serial.println("KO"); - } + aResult[idx++].res = SD.mkdir("STM32"); + aResult[idx++].res = SD.mkdir("ARDUINO"); + aResult[idx++].res = SD.mkdir("ARDUINO/SD"); /* Test bool operator method */ - Serial.print("Test bool operator..."); - if (!MyFile) { - Serial.println("OK"); - } else { - Serial.println("KO --> Error MyFile should not be initialized!"); - } + aResult[idx++].res = !MyFile; /* Test open() method */ - Serial.print("Opening 'STM32/Toremove.txt' file..."); MyFile = SD.open("STM32/Toremove.txt", FILE_WRITE); if (MyFile) { - Serial.println("OK"); - Serial.print("Closing 'STM32/Toremove.txt' file..."); + aResult[idx++].res = true; MyFile.close(); - Serial.println("OK"); } else { - Serial.println("KO --> Error to open 'STM32/Toremove.txt' file"); + idx += 1; } - Serial.print("Opening 'ARDUINO/SD/ARDUINO_SD_TEXT.txt' file..."); + MyFile = SD.open("ARDUINO/SD/ARDUINO_SD_TEXT.txt", FILE_WRITE); if (MyFile) { - Serial.println("OK"); + aResult[idx++].res = true; /* Test print() method */ - Serial.print(" writing \""); - Serial.print((const char*)wtext); - Serial.print("\" into ARDUINO_SD_TEXT.txt file..."); - byteswritten = MyFile.print((const char*)wtext); + byteswritten = MyFile.print(wtext); byteswritten += MyFile.print("\n"); - Serial.print(byteswritten, DEC); - Serial.println(" bytes written."); - Serial.print("Closing 'ARDUINO/SD/ARDUINO_SD_TEXT.txt' file..."); + aResult[idx++].res = (byteswritten == (BUFFERSIZE + 1)); MyFile.close(); - Serial.println("OK"); } else { - Serial.println("KO --> Error to open 'ARDUINO/SD/ARDUINO_SD_TEXT.txt' file"); + idx += 2; } - Serial.print("Opening 'ARDUINO/SD/ARDUINO_SD_TEXT.txt' file..."); MyFile = SD.open("ARDUINO/SD/ARDUINO_SD_TEXT.txt"); if (MyFile) { - Serial.println("OK"); - Serial.print(" reading ARDUINO/SD/ARDUINO_SD_TEXT.txt file..."); + aResult[idx++].res = true; bytesread = MyFile.read(rtext, MyFile.size()); - Serial.print(bytesread, DEC); - Serial.println(" bytes read."); - Serial.print("Closing 'ARDUINO/SD/ARDUINO_SD_TEXT.txt' file..."); + aResult[idx++].res = (bytesread == (BUFFERSIZE + 1)); MyFile.close(); - Serial.println("OK"); } else { - Serial.println("KO -- > Error to open 'ARDUINO/SD/ARDUINO_SD_TEXT.txt' file"); + idx += 2; } - Serial.print("Opening 'ARDUINO/SD/TEXT.txt' file..."); MyFile = SD.open("ARDUINO/SD/TEXT.txt", FILE_WRITE); if (MyFile) { - Serial.println("OK"); - Serial.print(" writing and flush \""); - Serial.print((const char*)rtext); - Serial.print("\" into ARDUINO/SD/TEXT.txt file..."); - byteswritten = MyFile.print((const char*)rtext); + aResult[idx++].res = true; + byteswritten = MyFile.print(rtext); MyFile.flush(); - Serial.print(byteswritten, DEC); - Serial.println(" bytes written."); - Serial.print("Closing 'ARDUINO/SD/TEXT.txt' file..."); + aResult[idx++].res = (byteswritten == (BUFFERSIZE + 1)); MyFile.close(); - Serial.println("OK"); } else { - Serial.println("KO --> Error to open 'ARDUINO/SD/TEXT.txt' file"); + idx += 2; } - Serial.print("Opening 'ARDUINO/SD/TEXT.txt' file..."); MyFile = SD.open("ARDUINO/SD/TEXT.txt"); if (MyFile) { - Serial.println("OK"); + aResult[idx++].res = true; /* Test size() method */ file_size = MyFile.size(); - Serial.print(" TEXT.txt size: "); - Serial.println(file_size); - + aResult[idx++].res = (file_size == (BUFFERSIZE + 1)); /* Test position and seek method */ - Serial.print(" TEXT.txt position value: "); - Serial.println(MyFile.position()); - Serial.print(" TEXT.txt seek value over size: "); - if (!MyFile.seek(MyFile.size() + 1)) { - Serial.println("OK"); - } else { - Serial.println("KO"); - } - Serial.print(" TEXT.txt seek value to size: "); - if (MyFile.seek(MyFile.size())) { - Serial.println("OK"); - } else { - Serial.println("KO"); - } - Serial.print(" TEXT.txt position value: "); - Serial.println(MyFile.position()); - Serial.print(" TEXT.txt seek value to 0: "); - if (MyFile.seek(0)) { - Serial.println("OK"); - } else { - Serial.println("KO"); - } - Serial.print(" TEXT.txt position value: "); - Serial.println(MyFile.position()); + aResult[idx++].res = (MyFile.position() == 0); + aResult[idx++].res = !MyFile.seek(MyFile.size() + 1); + aResult[idx++].res = MyFile.seek(MyFile.size()); + aResult[idx++].res = (MyFile.position() == (BUFFERSIZE + 1)); + aResult[idx++].res = MyFile.seek(0); + aResult[idx++].res = (MyFile.position() == 0); /* Test peek() method */ - Serial.println(" TEXT.txt peek (10 times): "); - for (i = 0; i < 10; i++) - { - peek_val = MyFile.peek(); - Serial.print(" "); - Serial.print(peek_val); - Serial.print(" '"); - Serial.write(peek_val); - Serial.println("'"); + aResult[idx].res = true; + for (i = 0; i < 10; i++) { + if (MyFile.peek() != wtext[0]) { + aResult[idx].res = false; + } } i = 0; + idx++; /* Test available() and read() methods */ - Serial.println(" TEXT.txt content read byte per byte: "); - while (MyFile.available()) - { - rtext[i] = (uint8_t)MyFile.read(); - Serial.print(" "); - Serial.print(rtext[i]); - Serial.print(" '"); - Serial.write(rtext[i]); - Serial.println("'"); - i++; + /* skip '\n' */ + aResult[idx].res = true; + while (MyFile.available() - 1) { + if (MyFile.read() != wtext[i++]) { + aResult[idx].res = false; + } } - /* Test close method */ - Serial.print("Closing 'ARDUINO/SD/TEXT.txt' file..."); + idx++; MyFile.close(); - Serial.println("OK"); } else { - Serial.println("KO --> Error to open 'ARDUINO/SD/TEXT.txt' file"); + idx += 10; } /* Test isDirectory() method */ - Serial.print("Opening 'STM32' dir..."); MyFile = SD.open("STM32"); if (MyFile) { - Serial.println("OK"); - Serial.print("Is 'STM32' is a dir..."); - if (MyFile.isDirectory()) { - Serial.println("OK"); - } else { - Serial.println("KO"); - } + aResult[idx++].res = true; + aResult[idx++].res = MyFile.isDirectory(); MyFile.close(); } else { - Serial.println("KO --> Error to open 'STM32' dir"); + idx += 2; } - Serial.print("Opening 'STM32/Toremove.txt' file..."); MyFile = SD.open("STM32/Toremove.txt"); if (MyFile) { - Serial.println("OK"); - Serial.print(" Is 'STM32/Toremove.txt' is a file: "); - if (MyFile.isDirectory()) { - Serial.println("KO"); - } else { - Serial.println("OK"); - } - Serial.print("Closing 'STM32/Toremove.txt' file..."); + aResult[idx++].res = true; + aResult[idx++].res = !MyFile.isDirectory(); MyFile.close(); - Serial.println("OK"); } else { - Serial.println("KO --> Error to open 'STM32/Toremove.txt' file"); + idx += 2; } /* Test exists(), remove() and rmdir() methods */ - Serial.print("Removing 'STM32/Toremove.txt' file..."); - while (SD.exists("STM32/Toremove.txt") == true) - { + while (SD.exists("STM32/Toremove.txt") == true) { SD.remove("STM32/Toremove.txt"); } - Serial.println("OK"); - - Serial.print("Removing 'STM32' dir..."); - while (SD.exists("STM32") == true) - { + aResult[idx++].res = true; + while (SD.exists("STM32") == true) { SD.rmdir("STM32"); } - Serial.println("OK"); + aResult[idx++].res = true; /* Test println(), println(data) methods */ - Serial.print("Opening 'ARDUINO/SD/PRINT.txt' file..."); MyFile = SD.open("ARDUINO/SD/PRINT.txt", FILE_WRITE); if (MyFile) { - Serial.println("OK"); + aResult[idx++].res = true; String str = String("This is a String object on line 7"); - Serial.print(" Printing to 'ARDUINO/SD/PRINT.txt' file..."); MyFile.println("This should be line 1"); MyFile.println(); MyFile.println("This should be line 3"); @@ -251,50 +206,55 @@ void setup() MyFile.println(); MyFile.println("This should be line 6"); MyFile.println(str); - Serial.println("OK"); - Serial.print("Closing 'ARDUINO/SD/PRINT.txt' file"); - Serial.println("OK"); + MyFile.print("This should be line "); + MyFile.println(8); + aResult[idx++].res = (MyFile.size() == 154); MyFile.close(); } else { - Serial.println("KO --> Error to open 'ARDUINO/SD/PRINT.txt' file"); + idx += 2; } /* Test write(buf, len) method */ - Serial.print("Opening 'ARDUINO/SD/WRITE.txt' file..."); MyFile = SD.open("ARDUINO/SD/WRITE.txt", FILE_WRITE); if (MyFile) { - Serial.println("OK"); - Serial.print(" Writing 'ARDUINO/SD/WRITE.txt' file: "); - byteswritten = MyFile.write(wtext, BUFFERSIZE); - Serial.print(byteswritten); - Serial.println(" bytes written"); - Serial.print("Closing 'ARDUINO/SD/WRITE.txt' file"); + aResult[idx++].res = true; + aResult[idx++].res = (MyFile.write(wtext, BUFFERSIZE) == BUFFERSIZE); MyFile.close(); - Serial.println("OK"); } else { - Serial.println("KO --> Error to open 'ARDUINO/SD/WRITE.txt' file"); + idx += 2; } /* Test read(buf, len) method */ - Serial.print("Opening 'ARDUINO/SD/WRITE.txt' file..."); MyFile = SD.open("ARDUINO/SD/WRITE.txt"); if (MyFile) { - Serial.println("OK"); - Serial.print(" Reading 'ARDUINO/SD/WRITE.txt' file: "); + aResult[idx++].res = true; bytesread = MyFile.read(rtext, MyFile.size()); - Serial.print(bytesread); - Serial.println(" bytes read"); - Serial.println((const char*)rtext); - Serial.print("Closing 'ARDUINO/SD/WRITE.txt' file..."); + aResult[idx++].res = (MyFile.size() == bytesread); + MyFile.close(); + } else { + idx += 2; + } + + /* Test readBytes(buf, len) method */ + MyFile = SD.open("ARDUINO/SD/WRITE.txt"); + if (MyFile) { + aResult[idx++].res = true; + bytesread = MyFile.readBytes(rtext, MyFile.size()); + aResult[idx++].res = (MyFile.size() == bytesread); MyFile.close(); - Serial.println("OK"); } else { - Serial.println("KO --> Error to open 'ARDUINO/SD/WRITE.txt' file"); + idx += 2; } + aResult[idx++].res = SD.end(); + + for (uint32_t i = 0; i < idx; i++) { + Serial.printf("%s %s\n", aResult[i].tst, (aResult[i].res) ? "OK" : (aResult[i].err) ? aResult[i].err + : "KO"); + } + Serial.println("###### End of the SD tests ######"); } -void loop() -{ +void loop() { // do nothing } diff --git a/examples/ReadWrite/ReadWrite.ino b/examples/ReadWrite/ReadWrite.ino index f344037..95f6cb7 100644 --- a/examples/ReadWrite/ReadWrite.ino +++ b/examples/ReadWrite/ReadWrite.ino @@ -19,18 +19,16 @@ File myFile; -void setup() -{ +void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { - ; // wait for serial port to connect. Needed for Leonardo only + ; // wait for serial port to connect. Needed for Leonardo only } Serial.print("Initializing SD card..."); - while (!SD.begin(SD_DETECT_PIN)) - { + while (!SD.begin(SD_DETECT_PIN)) { delay(10); } Serial.println("initialization done."); @@ -66,10 +64,12 @@ void setup() // if the file didn't open, print an error: Serial.println("error opening test.txt"); } + if (!SD.end()) { + Serial.println("Failed to properly end the SD."); + } Serial.println("###### End of the SD tests ######"); } -void loop() -{ +void loop() { // nothing happens after setup } diff --git a/examples/listfiles/listfiles.ino b/examples/listfiles/listfiles.ino index 3b891d4..a6870d6 100644 --- a/examples/listfiles/listfiles.ino +++ b/examples/listfiles/listfiles.ino @@ -20,63 +20,63 @@ File root; -void setup() -{ +void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { - ; // wait for Serial port to connect. Needed for Leonardo only + ; // wait for Serial port to connect. Needed for Leonardo only } Serial.print("Initializing SD card..."); - while (!SD.begin(SD_DETECT_PIN)) - { + while (!SD.begin(SD_DETECT_PIN)) { delay(10); } Serial.println("initialization done."); root = SD.open("/"); - if(root) + if (root) { printDirectory(root, 0); - else + delay(2000); + Serial.println(); + Serial.println("Rewinding, and repeating below:"); + Serial.println(); + delay(2000); + root.rewindDirectory(); + printDirectory(root, 0); + root.close(); + } else { Serial.println("Could not open root"); - delay(2000); - Serial.println(); - Serial.println("Rewinding, and repeating below:" ); - Serial.println(); - delay(2000); - root.rewindDirectory(); - printDirectory(root, 0); - root.close(); + } + if (!SD.end()) { + Serial.println("Failed to properly end the SD."); + } Serial.println("###### End of the SD tests ######"); } -void loop() -{ +void loop() { // nothing happens after setup finishes. } void printDirectory(File dir, int numTabs) { - while(true) { - File entry = dir.openNextFile(); - if (! entry) { - // no more files - break; - } - for (uint8_t i=0; iobj.fs = 0; file._dir.obj.fs = 0; #else @@ -263,7 +223,7 @@ void File::ls(uint8_t flags, uint8_t indent) char *fn; #if _USE_LFN -#if _FATFS == 68300 +#if (_FATFS == 68300) || (_FATFS == 80286) /* altname */ #else static char lfn[_MAX_LFN]; @@ -280,7 +240,7 @@ void File::ls(uint8_t flags, uint8_t indent) if (fno.fname[0] == '.') { continue; } -#if _USE_LFN && _FATFS != 68300 +#if _USE_LFN && (_FATFS != 68300 && _FATFS != 80286) fn = *fno.lfname ? fno.lfname : fno.fname; #else fn = fno.fname; @@ -414,7 +374,7 @@ int File::read(void *buf, size_t len) void File::close() { if (_name) { -#if _FATFS == 68300 +#if (_FATFS == 68300) || (_FATFS == 80286) if (_fil) { if (_fil->obj.fs != 0) { #else @@ -431,7 +391,7 @@ void File::close() _fil = NULL; } -#if _FATFS == 68300 +#if (_FATFS == 68300) || (_FATFS == 80286) if (_dir.obj.fs != 0) { #else if (_dir.fs != 0) { @@ -513,7 +473,7 @@ uint32_t File::size() File::operator bool() { -#if _FATFS == 68300 +#if (_FATFS == 68300) || (_FATFS == 80286) return !((_name == NULL) || ((_fil == NULL) && (_dir.obj.fs == 0)) || ((_fil != NULL) && (_fil->obj.fs == 0) && (_dir.obj.fs == 0))); #else return !((_name == NULL) || ((_fil == NULL) && (_dir.fs == 0)) || ((_fil != NULL) && (_fil->fs == 0) && (_dir.fs == 0))); @@ -547,47 +507,6 @@ size_t File::write(const uint8_t *buf, size_t size) return write((const char *)buf, size); } -/** - * @brief Print data to the file - * @param data: Data to write to the file - * @retval Number of data written (1) - */ -size_t File::print(const char *data) -{ - return write(data, strlen(data)); -} - -/** - * @brief Print data to the file - * @retval Number of data written (1) - */ -size_t File::println() -{ - return write("\r\n", 2); -} - -/** - * @brief Print data to the file - * @param data: Data to write to the file - * @retval Number of data written (1) - */ -size_t File::println(const char *data) -{ - size_t bytewritten = write(data, strlen(data)); - bytewritten += println(); - return bytewritten; -} - -/** - * @brief Print data to the file - * @param data: Data of type String to write to the file - * @retval Number of data written (1) - */ -size_t File::println(String &data) -{ - return println(data.c_str()); -} - /** * @brief Check if there are any bytes available for reading from the file * @retval Number of bytes available @@ -618,13 +537,13 @@ bool File::isDirectory() if (_name == NULL) { Error_Handler(); } -#if _FATFS == 68300 +#if (_FATFS == 68300) || (_FATFS == 80286) if (_dir.obj.fs != 0) #else if (_dir.fs != 0) #endif return true; -#if _FATFS == 68300 +#if (_FATFS == 68300) || (_FATFS == 80286) else if (_fil->obj.fs != 0) #else else if (_fil->fs != 0) @@ -645,7 +564,7 @@ File File::openNextFile(uint8_t mode) FRESULT res = FR_OK; FILINFO fno; char *fn; -#if _USE_LFN && _FATFS != 68300 +#if _USE_LFN && (_FATFS != 68300 && _FATFS != 80286) static char lfn[_MAX_LFN]; fno.lfname = lfn; fno.lfsize = sizeof(lfn); @@ -658,7 +577,7 @@ File File::openNextFile(uint8_t mode) if (fno.fname[0] == '.') { continue; } -#if _USE_LFN && _FATFS != 68300 +#if _USE_LFN && (_FATFS != 68300 && _FATFS != 80286) fn = *fno.lfname ? fno.lfname : fno.fname; #else fn = fno.fname; @@ -684,7 +603,7 @@ File File::openNextFile(uint8_t mode) void File::rewindDirectory(void) { if (isDirectory()) { -#if _FATFS == 68300 +#if (_FATFS == 68300) || (_FATFS == 80286) if (_dir.obj.fs != 0) { #else if (_dir.fs != 0) { diff --git a/src/STM32SD.h b/src/STM32SD.h index 8033e2a..ed52396 100644 --- a/src/STM32SD.h +++ b/src/STM32SD.h @@ -22,6 +22,10 @@ #include "Sd2Card.h" #include "SdFatFs.h" +#ifndef HAL_SD_MODULE_ENABLED + #error "HAL_SD_MODULE_ENABLED is required" +#endif + // flags for ls() /** ls() flag to print modify date */ uint8_t const LS_DATE = 1; @@ -30,7 +34,7 @@ uint8_t const LS_SIZE = 2; /** ls() flag for recursive list of subdirectories */ uint8_t const LS_R = 4; -class File { +class File : public Stream { public: File(FRESULT res = FR_OK); virtual size_t write(uint8_t); @@ -57,11 +61,6 @@ class File { File openNextFile(uint8_t mode = FILE_READ); void rewindDirectory(void); - virtual size_t print(const char *data); - virtual size_t println(); - virtual size_t println(const char *data); - virtual size_t println(String &data); - // Print to Serial line void ls(uint8_t flags, uint8_t indent = 0); static void printFatDate(uint16_t fatDate); @@ -78,6 +77,8 @@ class File { { return _res; } + using Print::println; + using Print::print; }; @@ -85,23 +86,12 @@ class SDClass { public: /* Initialize the SD peripheral */ -#if defined(SDMMC1) || defined(SDMMC2) - bool begin(uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3, uint32_t ck, uint32_t cmd, - uint32_t ckin, uint32_t cdir, uint32_t d0dir, uint32_t d123dir - ); - bool begin(uint32_t detect = SD_DETECT_NONE, uint32_t data0 = SDX_D0, uint32_t data1 = SDX_D1, - uint32_t data2 = SDX_D2, uint32_t data3 = SDX_D3, uint32_t ck = SDX_CK, uint32_t cmd = SDX_CMD, - uint32_t ckin = SDX_CKIN, uint32_t cdir = SDX_CDIR, uint32_t d0dir = SDX_D0DIR, uint32_t d123dir = SDX_D123DIR - ); -#else - bool begin(uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3, uint32_t ck, uint32_t cmd); - bool begin(uint32_t detect = SD_DETECT_NONE, uint32_t data0 = SDX_D0, uint32_t data1 = SDX_D1, - uint32_t data2 = SDX_D2, uint32_t data3 = SDX_D3, uint32_t ck = SDX_CMD, uint32_t cmd = SDX_CMD - ); -#endif + bool begin(uint32_t detect = SD_DETECT_NONE, uint32_t level = SD_DETECT_LEVEL); + /* Call this when a card is removed. It will allow to insert and initialise a new card. */ + bool end(void); // set* have to be called before begin() - void setDx(uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3) + void setDx(uint32_t data0, uint32_t data1 = PNUM_NOT_DEFINED, uint32_t data2 = PNUM_NOT_DEFINED, uint32_t data3 = PNUM_NOT_DEFINED) { _card.setDx(data0, data1, data2, data3); }; @@ -114,7 +104,7 @@ class SDClass { _card.setCMD(cmd); }; - void setDx(PinName data0, PinName data1, PinName data2, PinName data3) + void setDx(PinName data0, PinName data1 = NC, PinName data2 = NC, PinName data3 = NC) { _card.setDx(data0, data1, data2, data3); }; diff --git a/src/Sd2Card.cpp b/src/Sd2Card.cpp index 2c7cb8a..0b06b17 100644 --- a/src/Sd2Card.cpp +++ b/src/Sd2Card.cpp @@ -37,40 +37,27 @@ #include #include "Sd2Card.h" -#if defined(SDMMC1) || defined(SDMMC2) -bool Sd2Card::init(uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3, uint32_t ck, uint32_t cmd, - uint32_t ckin, uint32_t cdir, uint32_t d0dir, uint32_t d123dir) -{ - return init(SD_DETECT_NONE, data0, data1, data2, data3, ck, cmd, ckin, cdir, d0dir, d123dir); -} -#else -bool Sd2Card::init(uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3, uint32_t ck, uint32_t cmd) +/** + * @brief Default constructor. Use default pins definition. + */ +Sd2Card::Sd2Card() { - return init(SD_DETECT_NONE, data0, data1, data2, data3, ck, cmd); -} -#endif - + setDx(SDX_D0, SDX_D1, SDX_D2, SDX_D3); + setCK(SDX_CK); + setCMD(SDX_CMD); #if defined(SDMMC1) || defined(SDMMC2) -bool Sd2Card::init(uint32_t detect, uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3, - uint32_t ck, uint32_t cmd, uint32_t ckin, uint32_t cdir, uint32_t d0dir, uint32_t d123dir) -#else -bool Sd2Card::init(uint32_t detect, uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3, - uint32_t ck, uint32_t cmd) + setCKIN(SDX_CKIN); + setCDIR(SDX_CDIR); + setDxDIR(SDX_D0DIR, SDX_D123DIR); #endif +} + +bool Sd2Card::init(uint32_t detect, uint32_t level) { - setDx(data0, data1, data2, data3); - setCK(ck); - setCMD(cmd); -#if defined(SDMMC1) || defined(SDMMC2) - setCKIN(ckin); - setCDIR(cdir); - setDxDIR(d0dir, d123dir); -#endif if (detect != SD_DETECT_NONE) { PinName p = digitalPinToPinName(detect); if ((p == NC) || \ - BSP_SD_DetectPin(set_GPIO_Port_Clock(STM_PORT(p)), - STM_LL_GPIO_PIN(p)) != MSD_OK) { + BSP_SD_DetectPin(p, level) != MSD_OK) { return false; } } @@ -91,6 +78,14 @@ bool Sd2Card::init(uint32_t detect, uint32_t data0, uint32_t data1, uint32_t dat return false; } +bool Sd2Card::deinit(void) +{ + if (BSP_SD_DeInit() == MSD_OK) { + return true; + } + return false; +} + uint8_t Sd2Card::type(void) const { uint8_t cardType = SD_CARD_TYPE_UKN; diff --git a/src/Sd2Card.h b/src/Sd2Card.h index 6942bcf..69d6818 100644 --- a/src/Sd2Card.h +++ b/src/Sd2Card.h @@ -52,23 +52,13 @@ class Sd2Card { public: -#if defined(SDMMC1) || defined(SDMMC2) - bool init(uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3, uint32_t ck, uint32_t cmd, - uint32_t ckin, uint32_t cdir, uint32_t d0dir, uint32_t d123dir - ); - bool init(uint32_t detect = SD_DETECT_NONE, uint32_t data0 = SDX_D0, uint32_t data1 = SDX_D1, - uint32_t data2 = SDX_D2, uint32_t data3 = SDX_D3, uint32_t ck = SDX_CK, uint32_t cmd = SDX_CMD, - uint32_t ckin = SDX_CKIN, uint32_t cdir = SDX_CDIR, uint32_t d0dir = SDX_D0DIR, uint32_t d123dir = SDX_D123DIR - ); -#else - bool init(uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3, uint32_t ck, uint32_t cmd); - bool init(uint32_t detect = SD_DETECT_NONE, uint32_t data0 = SDX_D0, uint32_t data1 = SDX_D1, - uint32_t data2 = SDX_D2, uint32_t data3 = SDX_D3, uint32_t ck = SDX_CK, uint32_t cmd = SDX_CMD - ); -#endif + Sd2Card(); + + bool init(uint32_t detect = SD_DETECT_NONE, uint32_t level = SD_DETECT_LEVEL); + bool deinit(void); // set* have to be called before init() - void setDx(uint32_t data0, uint32_t data1, uint32_t data2, uint32_t data3) + void setDx(uint32_t data0, uint32_t data1 = PNUM_NOT_DEFINED, uint32_t data2 = PNUM_NOT_DEFINED, uint32_t data3 = PNUM_NOT_DEFINED) { SD_PinNames.pin_d0 = digitalPinToPinName(data0); SD_PinNames.pin_d1 = digitalPinToPinName(data1); @@ -84,7 +74,7 @@ class Sd2Card { SD_PinNames.pin_cmd = digitalPinToPinName(cmd); }; - void setDx(PinName data0, PinName data1, PinName data2, PinName data3) + void setDx(PinName data0, PinName data1 = NC, PinName data2 = NC, PinName data3 = NC) { SD_PinNames.pin_d0 = data0; SD_PinNames.pin_d1 = data1; diff --git a/src/SdFatFs.cpp b/src/SdFatFs.cpp index 9dea4bd..c59c6cc 100644 --- a/src/SdFatFs.cpp +++ b/src/SdFatFs.cpp @@ -51,6 +51,19 @@ bool SdFatFs::init(void) return false; } +bool SdFatFs::deinit(void) +{ + /*##-1- Unregister the file system object to the FatFs module ##############*/ + if (f_unmount((TCHAR const *)_SDPath) == FR_OK) { + /*##-2- Unlink the SD disk I/O driver ####################################*/ + if (FATFS_UnLinkDriver(_SDPath) == 0) { + /* FatFs deInitialization done */ + return true; + } + } + return false; +} + uint8_t SdFatFs::fatType(void) { switch (_SDFatFs.fs_type) { diff --git a/src/SdFatFs.h b/src/SdFatFs.h index fdef3ba..6f7be73 100644 --- a/src/SdFatFs.h +++ b/src/SdFatFs.h @@ -82,6 +82,7 @@ class SdFatFs { public: bool init(void); + bool deinit(void); /** Return the FatFs type: 12, 16, 32 (0: unknown)*/ uint8_t fatType(void); diff --git a/src/bsp_sd.c b/src/bsp_sd.c index 8d797b5..59d813f 100644 --- a/src/bsp_sd.c +++ b/src/bsp_sd.c @@ -57,7 +57,6 @@ #define SD_CLK_PWR_SAVE SDMMC_CLOCK_POWER_SAVE_DISABLE #define SD_BUS_WIDE_1B SDMMC_BUS_WIDE_1B #define SD_BUS_WIDE_4B SDMMC_BUS_WIDE_4B - #define SD_BUS_WIDE_8B SDMMC_BUS_WIDE_8B #define SD_HW_FLOW_CTRL_ENABLE SDMMC_HARDWARE_FLOW_CONTROL_ENABLE #define SD_HW_FLOW_CTRL_DISABLE SDMMC_HARDWARE_FLOW_CONTROL_DISABLE @@ -88,7 +87,6 @@ #define SD_CLK_PWR_SAVE SDIO_CLOCK_POWER_SAVE_DISABLE #define SD_BUS_WIDE_1B SDIO_BUS_WIDE_1B #define SD_BUS_WIDE_4B SDIO_BUS_WIDE_4B - #define SD_BUS_WIDE_8B SDIO_BUS_WIDE_8B #define SD_HW_FLOW_CTRL_ENABLE SDIO_HARDWARE_FLOW_CONTROL_ENABLE #define SD_HW_FLOW_CTRL_DISABLE SDIO_HARDWARE_FLOW_CONTROL_DISABLE #ifndef SD_CLK_DIV @@ -110,6 +108,7 @@ static SD_HandleTypeDef uSdHandle; static uint32_t SD_detect_ll_gpio_pin = LL_GPIO_PIN_ALL; static GPIO_TypeDef *SD_detect_gpio_port = GPIOA; +static uint32_t SD_detect_level = SD_DETECT_LEVEL; #if defined(USE_SD_TRANSCEIVER) && (USE_SD_TRANSCEIVER != 0U) static uint32_t SD_trans_en_ll_gpio_pin = LL_GPIO_PIN_ALL; static GPIO_TypeDef *SD_trans_en_gpio_port = GPIOA; @@ -147,40 +146,60 @@ uint8_t BSP_SD_GetInstance(void) SD_TypeDef *sd_cmd = NP; SD_TypeDef *sd_ck = NP; + /* If a pin is not defined, use the first pin available in the associated PinMap_SD_* arrays */ if (SD_PinNames.pin_d0 == NC) { - /* No pin defined assume to use first pin available in each PinMap_SD_* arrays */ SD_PinNames.pin_d0 = PinMap_SD_DATA0[0].pin; +#if SD_BUS_WIDE == SD_BUS_WIDE_4B SD_PinNames.pin_d1 = PinMap_SD_DATA1[0].pin; SD_PinNames.pin_d2 = PinMap_SD_DATA2[0].pin; SD_PinNames.pin_d3 = PinMap_SD_DATA3[0].pin; +#endif + } + if (SD_PinNames.pin_cmd == NC) { SD_PinNames.pin_cmd = PinMap_SD_CMD[0].pin; + } + if (SD_PinNames.pin_ck == NC) { SD_PinNames.pin_ck = PinMap_SD_CK[0].pin; + } #if defined(SDMMC1) || defined(SDMMC2) #if !defined(SDMMC_CKIN_NA) + if (SD_PinNames.pin_ckin == NC) { SD_PinNames.pin_ckin = PinMap_SD_CKIN[0].pin; + } #endif #if !defined(SDMMC_CDIR_NA) + if (SD_PinNames.pin_cdir == NC) { SD_PinNames.pin_cdir = PinMap_SD_CDIR[0].pin; + } #endif #if !defined(SDMMC_D0DIR_NA) + if (SD_PinNames.pin_d0dir == NC) { SD_PinNames.pin_d0dir = PinMap_SD_D0DIR[0].pin; + } #endif #if !defined(SDMMC_D123DIR_NA) + if (SD_PinNames.pin_d123dir == NC) { SD_PinNames.pin_d123dir = PinMap_SD_D123DIR[0].pin; + } #endif #endif /* SDMMC1 || SDMMC2 */ - } + /* Get SD instance from pins */ sd_d0 = pinmap_peripheral(SD_PinNames.pin_d0, PinMap_SD_DATA0); +#if SD_BUS_WIDE == SD_BUS_WIDE_4B sd_d1 = pinmap_peripheral(SD_PinNames.pin_d1, PinMap_SD_DATA1); sd_d2 = pinmap_peripheral(SD_PinNames.pin_d2, PinMap_SD_DATA2); sd_d3 = pinmap_peripheral(SD_PinNames.pin_d3, PinMap_SD_DATA3); - +#endif sd_cmd = pinmap_peripheral(SD_PinNames.pin_cmd, PinMap_SD_CMD); sd_ck = pinmap_peripheral(SD_PinNames.pin_ck, PinMap_SD_CK); /* Pins Dx/cmd/CK must not be NP. */ - if (sd_d0 == NP || sd_d1 == NP || sd_d2 == NP || sd_d3 == NP || sd_cmd == NP || sd_ck == NP) { + if (sd_d0 == NP || +#if SD_BUS_WIDE == SD_BUS_WIDE_4B + sd_d1 == NP || sd_d2 == NP || sd_d3 == NP || +#endif + sd_cmd == NP || sd_ck == NP) { core_debug("ERROR: at least one SD pin has no peripheral\n"); return MSD_ERROR; } @@ -190,7 +209,11 @@ uint8_t BSP_SD_GetInstance(void) SD_TypeDef *sd_cx = pinmap_merge_peripheral(sd_cmd, sd_ck); SD_TypeDef *sd_dx = pinmap_merge_peripheral(sd_d01, sd_d23); SD_TypeDef *sd_base = pinmap_merge_peripheral(sd_dx, sd_cx); - if (sd_d01 == NP || sd_d23 == NP || sd_cx == NP || sd_dx == NP || sd_base == NP) { + if (sd_d01 == NP || +#if SD_BUS_WIDE == SD_BUS_WIDE_4B + sd_d23 == NP || +#endif + sd_cx == NP || sd_dx == NP || sd_base == NP) { core_debug("ERROR: SD pins mismatch\n"); return MSD_ERROR; } @@ -331,6 +354,15 @@ uint8_t BSP_SD_DeInit(void) /* Msp SD deinitialization */ BSP_SD_MspDeInit(&uSdHandle, NULL); + + if (SD_detect_ll_gpio_pin != LL_GPIO_PIN_ALL) { + BSP_SD_Detect_MspDeInit(&uSdHandle, NULL); + } +#if defined(USE_SD_TRANSCEIVER) && (USE_SD_TRANSCEIVER != 0U) + BSP_SD_Transceiver_MspDeInit(&uSdHandle, NULL); +#endif + + return sd_state; } @@ -357,102 +389,32 @@ uint8_t BSP_SD_TransceiverPin(GPIO_TypeDef *enport, uint32_t enpin, GPIO_TypeDef #endif /** - * @brief Set the SD card device detect pin and port. - * @param port one of the gpio port - * @param pin one of the gpio pin + * @brief Set the SD card device detect pin, port and level. + * @param p PinName of the detect pin + * @param level the level of the detect pin (HIGH or LOW) * @retval SD status */ -uint8_t BSP_SD_DetectPin(GPIO_TypeDef *port, uint32_t pin) +uint8_t BSP_SD_DetectPin(PinName p, uint32_t level) { + GPIO_TypeDef *port = set_GPIO_Port_Clock(STM_PORT(p)); + uint32_t pin = STM_LL_GPIO_PIN(p); if (port != 0) { SD_detect_ll_gpio_pin = pin; SD_detect_gpio_port = port; + SD_detect_level = level; return MSD_OK; } return MSD_ERROR; } -/** - * @brief Configures Interrupt mode for SD detection pin. - * @retval Status - */ -uint8_t BSP_SD_DetectITConfig(void (*callback)(void)) -{ - uint8_t sd_state = MSD_ERROR; - if (SD_detect_ll_gpio_pin != LL_GPIO_PIN_ALL) { - LL_GPIO_SetPinPull(SD_detect_gpio_port, SD_detect_ll_gpio_pin, LL_GPIO_PULL_UP); - uint16_t SD_detect_gpio_pin = GPIO_PIN_All; - switch (SD_detect_ll_gpio_pin) { - case LL_GPIO_PIN_0: - SD_detect_gpio_pin = GPIO_PIN_0; - break; - case LL_GPIO_PIN_1: - SD_detect_gpio_pin = GPIO_PIN_1; - break; - case LL_GPIO_PIN_2: - SD_detect_gpio_pin = GPIO_PIN_2; - break; - case LL_GPIO_PIN_3: - SD_detect_gpio_pin = GPIO_PIN_3; - break; - case LL_GPIO_PIN_4: - SD_detect_gpio_pin = GPIO_PIN_4; - break; - case LL_GPIO_PIN_5: - SD_detect_gpio_pin = GPIO_PIN_5; - break; - case LL_GPIO_PIN_6: - SD_detect_gpio_pin = GPIO_PIN_6; - break; - case LL_GPIO_PIN_7: - SD_detect_gpio_pin = GPIO_PIN_7; - break; - case LL_GPIO_PIN_8: - SD_detect_gpio_pin = GPIO_PIN_8; - break; - case LL_GPIO_PIN_9: - SD_detect_gpio_pin = GPIO_PIN_9; - break; - case LL_GPIO_PIN_10: - SD_detect_gpio_pin = GPIO_PIN_10; - break; - case LL_GPIO_PIN_11: - SD_detect_gpio_pin = GPIO_PIN_11; - break; - case LL_GPIO_PIN_12: - SD_detect_gpio_pin = GPIO_PIN_12; - break; - case LL_GPIO_PIN_13: - SD_detect_gpio_pin = GPIO_PIN_13; - break; - case LL_GPIO_PIN_14: - SD_detect_gpio_pin = GPIO_PIN_14; - break; - case LL_GPIO_PIN_15: - SD_detect_gpio_pin = GPIO_PIN_15; - break; - default: - Error_Handler(); - break; - } - stm32_interrupt_enable(SD_detect_gpio_port, SD_detect_gpio_pin, callback, GPIO_MODE_IT_RISING_FALLING); - sd_state = MSD_OK; - } - return sd_state; -} - /** * @brief Detects if SD card is correctly plugged in the memory slot or not. * @retval Returns if SD is detected or not */ uint8_t BSP_SD_IsDetected(void) { - uint8_t status = SD_NOT_PRESENT; /* Check SD card detect pin */ - if (!LL_GPIO_IsInputPinSet(SD_detect_gpio_port, SD_detect_ll_gpio_pin)) { - status = SD_PRESENT; - } - return status; + return (LL_GPIO_IsInputPinSet(SD_detect_gpio_port, SD_detect_ll_gpio_pin) == SD_detect_level) ? SD_PRESENT : SD_NOT_PRESENT; } /** @@ -522,9 +484,11 @@ __weak void BSP_SD_MspInit(SD_HandleTypeDef *hsd, void *Params) #else /* Configure SD GPIO pins */ pinmap_pinout(SD_PinNames.pin_d0, PinMap_SD_DATA0); +#if SD_BUS_WIDE == SD_BUS_WIDE_4B pinmap_pinout(SD_PinNames.pin_d1, PinMap_SD_DATA1); pinmap_pinout(SD_PinNames.pin_d2, PinMap_SD_DATA2); pinmap_pinout(SD_PinNames.pin_d3, PinMap_SD_DATA3); +#endif pinmap_pinout(SD_PinNames.pin_cmd, PinMap_SD_CMD); pinmap_pinout(SD_PinNames.pin_ck, PinMap_SD_CK); #if defined(SDMMC1) || defined(SDMMC2) @@ -568,26 +532,6 @@ __weak void BSP_SD_MspInit(SD_HandleTypeDef *hsd, void *Params) #endif } -/** - * @brief Initializes the SD Detect pin MSP. - * @param hsd: SD handle - * @param Params : pointer on additional configuration parameters, can be NULL. - */ -__weak void BSP_SD_Detect_MspInit(SD_HandleTypeDef *hsd, void *Params) -{ - UNUSED(hsd); - UNUSED(Params); - - /* GPIO configuration in input for uSD_Detect signal */ -#ifdef LL_GPIO_SPEED_FREQ_VERY_HIGH - LL_GPIO_SetPinSpeed(SD_detect_gpio_port, SD_detect_ll_gpio_pin, LL_GPIO_SPEED_FREQ_VERY_HIGH); -#else - LL_GPIO_SetPinSpeed(SD_detect_gpio_port, SD_detect_ll_gpio_pin, LL_GPIO_SPEED_FREQ_HIGH); -#endif - LL_GPIO_SetPinMode(SD_detect_gpio_port, SD_detect_ll_gpio_pin, LL_GPIO_MODE_INPUT); - LL_GPIO_SetPinPull(SD_detect_gpio_port, SD_detect_ll_gpio_pin, LL_GPIO_PULL_UP); -} - /** * @brief DeInitializes the SD MSP. * @param hsd: SD handle @@ -653,6 +597,47 @@ __weak void BSP_SD_MspDeInit(SD_HandleTypeDef *hsd, void *Params) #endif } +/** + * @brief Initializes the SD Detect pin MSP. + * @param hsd: SD handle + * @param Params : pointer on additional configuration parameters, can be NULL. + */ +__weak void BSP_SD_Detect_MspInit(SD_HandleTypeDef *hsd, void *Params) +{ + UNUSED(hsd); + UNUSED(Params); + + /* GPIO configuration in input for uSD_Detect signal */ +#ifdef LL_GPIO_SPEED_FREQ_VERY_HIGH + LL_GPIO_SetPinSpeed(SD_detect_gpio_port, SD_detect_ll_gpio_pin, LL_GPIO_SPEED_FREQ_VERY_HIGH); +#else + LL_GPIO_SetPinSpeed(SD_detect_gpio_port, SD_detect_ll_gpio_pin, LL_GPIO_SPEED_FREQ_HIGH); +#endif + LL_GPIO_SetPinMode(SD_detect_gpio_port, SD_detect_ll_gpio_pin, LL_GPIO_MODE_INPUT); + LL_GPIO_SetPinPull(SD_detect_gpio_port, SD_detect_ll_gpio_pin, LL_GPIO_PULL_UP); +} + +/** + * @brief DeInitializes the SD Detect pin MSP. + * @param hsd: SD handle + * @param Params : pointer on additional configuration parameters, can be NULL. + */ +__weak void BSP_SD_Detect_MspDeInit(SD_HandleTypeDef *hsd, void *Params) +{ + UNUSED(hsd); + UNUSED(Params); + + /* GPIO configuration in analog to saves the consumption */ + LL_GPIO_SetPinSpeed(SD_detect_gpio_port, SD_detect_ll_gpio_pin, LL_GPIO_SPEED_FREQ_LOW); +#ifndef LL_GPIO_PULL_NO + /* For STM32F1xx */ + LL_GPIO_SetPinPull(SD_detect_gpio_port, SD_detect_ll_gpio_pin, LL_GPIO_MODE_FLOATING); +#else + LL_GPIO_SetPinPull(SD_detect_gpio_port, SD_detect_ll_gpio_pin, LL_GPIO_PULL_NO); +#endif + LL_GPIO_SetPinMode(SD_detect_gpio_port, SD_detect_ll_gpio_pin, LL_GPIO_MODE_ANALOG); +} + #if defined(USE_SD_TRANSCEIVER) && (USE_SD_TRANSCEIVER != 0U) /** * @brief Initializes the SD Transceiver pin MSP. @@ -666,12 +651,20 @@ __weak void BSP_SD_Transceiver_MspInit(SD_HandleTypeDef *hsd, void *Params) LL_GPIO_SetPinSpeed(SD_trans_en_gpio_port, SD_trans_en_ll_gpio_pin, LL_GPIO_SPEED_FREQ_HIGH); LL_GPIO_SetPinMode(SD_trans_en_gpio_port, SD_trans_en_ll_gpio_pin, LL_GPIO_MODE_OUTPUT); +#ifndef LL_GPIO_PULL_NO + /* For STM32F1xx */ + LL_GPIO_SetPinPull(SD_detect_gpio_port, SD_detect_ll_gpio_pin, LL_GPIO_MODE_FLOATING); +#else LL_GPIO_SetPinPull(SD_trans_en_gpio_port, SD_trans_en_ll_gpio_pin, LL_GPIO_PULL_NO); - +#endif LL_GPIO_SetPinSpeed(SD_trans_sel_gpio_port, SD_trans_sel_ll_gpio_pin, LL_GPIO_SPEED_FREQ_HIGH); LL_GPIO_SetPinMode(SD_trans_sel_gpio_port, SD_trans_sel_ll_gpio_pin, LL_GPIO_MODE_OUTPUT); +#ifndef LL_GPIO_PULL_NO + /* For STM32F1xx */ + LL_GPIO_SetPinPull(SD_detect_gpio_port, SD_detect_ll_gpio_pin, LL_GPIO_MODE_FLOATING); +#else LL_GPIO_SetPinPull(SD_trans_sel_gpio_port, SD_trans_sel_ll_gpio_pin, LL_GPIO_PULL_NO); - +#endif /* Enable the level shifter */ LL_GPIO_SetOutputPin(SD_trans_en_gpio_port, SD_trans_en_ll_gpio_pin); @@ -679,6 +672,25 @@ __weak void BSP_SD_Transceiver_MspInit(SD_HandleTypeDef *hsd, void *Params) LL_GPIO_ResetOutputPin(SD_trans_sel_gpio_port, SD_trans_sel_ll_gpio_pin); } +/** + * @brief DeInitializes the SD Transceiver pin MSP. + * @param hsd: SD handle + * @param Params : pointer on additional configuration parameters, can be NULL. + */ +__weak void BSP_SD_Transceiver_MspDeInit(SD_HandleTypeDef *hsd, void *Params) +{ + UNUSED(hsd); + UNUSED(Params); + + LL_GPIO_SetPinSpeed(SD_trans_en_gpio_port, SD_trans_en_ll_gpio_pin, LL_GPIO_SPEED_FREQ_LOW); + LL_GPIO_SetPinMode(SD_trans_en_gpio_port, SD_trans_en_ll_gpio_pin, LL_GPIO_MODE_ANALOG); + LL_GPIO_SetPinPull(SD_trans_en_gpio_port, SD_trans_en_ll_gpio_pin, LL_GPIO_PULL_NO); + + LL_GPIO_SetPinSpeed(SD_trans_sel_gpio_port, SD_trans_sel_ll_gpio_pin, LL_GPIO_SPEED_FREQ_LOW); + LL_GPIO_SetPinMode(SD_trans_sel_gpio_port, SD_trans_sel_ll_gpio_pin, LL_GPIO_MODE_ANALOG); + LL_GPIO_SetPinPull(SD_trans_sel_gpio_port, SD_trans_sel_ll_gpio_pin, LL_GPIO_PULL_NO); +} + /** * @brief Enable/Disable the SD Transceiver 1.8V Mode Callback. * @param status: Voltage Switch State diff --git a/src/bsp_sd.h b/src/bsp_sd.h index 20f7fc1..3828ee6 100644 --- a/src/bsp_sd.h +++ b/src/bsp_sd.h @@ -47,6 +47,7 @@ extern "C" { #include "PinNames.h" #include "stm32_def.h" #include "variant.h" +#include "wiring_constants.h" #if !defined(STM32_CORE_VERSION) || (STM32_CORE_VERSION <= 0x01060100) #error "This library version required a STM32 core version > 1.6.1.\ Please update the core or install previous library version." @@ -73,6 +74,9 @@ Please update the core or install previous library version." #define SD_DETECT_NONE NUM_DIGITAL_PINS /* Could be redefined in variant.h or using build_opt.h */ +#ifndef SD_DETECT_LEVEL +#define SD_DETECT_LEVEL LOW +#endif #ifndef SD_DATATIMEOUT #define SD_DATATIMEOUT 100000000U #endif @@ -115,35 +119,35 @@ Please update the core or install previous library version." /* Default SDx pins definitions */ #ifndef SDX_D0 -#define SDX_D0 NUM_DIGITAL_PINS +#define SDX_D0 PNUM_NOT_DEFINED #endif #ifndef SDX_D1 -#define SDX_D1 NUM_DIGITAL_PINS +#define SDX_D1 PNUM_NOT_DEFINED #endif #ifndef SDX_D2 -#define SDX_D2 NUM_DIGITAL_PINS +#define SDX_D2 PNUM_NOT_DEFINED #endif #ifndef SDX_D3 -#define SDX_D3 NUM_DIGITAL_PINS +#define SDX_D3 PNUM_NOT_DEFINED #endif #ifndef SDX_CMD -#define SDX_CMD NUM_DIGITAL_PINS +#define SDX_CMD PNUM_NOT_DEFINED #endif #ifndef SDX_CK -#define SDX_CK NUM_DIGITAL_PINS +#define SDX_CK PNUM_NOT_DEFINED #endif #if defined(SDMMC1) || defined(SDMMC2) #ifndef SDX_CKIN -#define SDX_CKIN NUM_DIGITAL_PINS +#define SDX_CKIN PNUM_NOT_DEFINED #endif #ifndef SDX_CDIR -#define SDX_CDIR NUM_DIGITAL_PINS +#define SDX_CDIR PNUM_NOT_DEFINED #endif #ifndef SDX_D0DIR -#define SDX_D0DIR NUM_DIGITAL_PINS +#define SDX_D0DIR PNUM_NOT_DEFINED #endif #ifndef SDX_D123DIR -#define SDX_D123DIR NUM_DIGITAL_PINS +#define SDX_D123DIR PNUM_NOT_DEFINED #endif #endif /* SDMMC1 || SDMMC2 */ @@ -170,8 +174,7 @@ uint8_t BSP_SD_DeInit(void); #if defined(USE_SD_TRANSCEIVER) && (USE_SD_TRANSCEIVER != 0U) uint8_t BSP_SD_TransceiverPin(GPIO_TypeDef *enport, uint32_t enpin, GPIO_TypeDef *selport, uint32_t selpin); #endif -uint8_t BSP_SD_DetectPin(GPIO_TypeDef *port, uint32_t pin); -uint8_t BSP_SD_DetectITConfig(void (*callback)(void)); +uint8_t BSP_SD_DetectPin(PinName p, uint32_t level); uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout); uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout); uint8_t BSP_SD_Erase(uint64_t StartAddr, uint64_t EndAddr); @@ -182,10 +185,12 @@ uint8_t BSP_SD_IsDetected(void); /* These __weak function can be surcharged by application code in case the current settings (e.g. DMA stream) need to be changed for specific needs */ void BSP_SD_MspInit(SD_HandleTypeDef *hsd, void *Params); -void BSP_SD_Detect_MspInit(SD_HandleTypeDef *hsd, void *Params); void BSP_SD_MspDeInit(SD_HandleTypeDef *hsd, void *Params); +void BSP_SD_Detect_MspInit(SD_HandleTypeDef *hsd, void *Params); +void BSP_SD_Detect_MspDeInit(SD_HandleTypeDef *hsd, void *Params); #if defined(USE_SD_TRANSCEIVER) && (USE_SD_TRANSCEIVER != 0U) void BSP_SD_Transceiver_MspInit(SD_HandleTypeDef *hsd, void *Params); +void BSP_SD_Transceiver_MspDeInit(SD_HandleTypeDef *hsd, void *Params); #endif #ifdef __cplusplus diff --git a/src/ffconf.h b/src/ffconf.h index 3120ca0..f73d58c 100644 --- a/src/ffconf.h +++ b/src/ffconf.h @@ -12,7 +12,17 @@ #if __has_include("ffconf_custom.h") #include "ffconf_custom.h" #else - #if _FATFS == 68300 + #if defined(FF_DEFINED) && !defined(_FATFS) + #define _FATFS FF_DEFINED + #endif + + #if _FATFS == 80286 + /* Ensure backward compatibility with release prior to FatFs 0.14 */ + /* Those flags are */ + #define _USE_WRITE 1 + #define _USE_IOCTL 1 + #include "ffconf_default_80286.h" + #elif _FATFS == 68300 #include "ffconf_default_68300.h" #else #include "ffconf_default_32020.h" diff --git a/src/ffconf_default_80286.h b/src/ffconf_default_80286.h new file mode 100644 index 0000000..1c54994 --- /dev/null +++ b/src/ffconf_default_80286.h @@ -0,0 +1,296 @@ +/*---------------------------------------------------------------------------/ +/ Configurations of FatFs Module +/---------------------------------------------------------------------------*/ + +#define FFCONF_DEF 80286 /* Revision ID */ + +/*---------------------------------------------------------------------------/ +/ Function Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_READONLY 0 +/* This option switches read-only configuration. (0:Read/Write or 1:Read-only) +/ Read-only configuration removes writing API functions, f_write(), f_sync(), +/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() +/ and optional writing functions as well. */ + + +#define FF_FS_MINIMIZE 0 +/* This option defines minimization level to remove some basic API functions. +/ +/ 0: Basic functions are fully enabled. +/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() +/ are removed. +/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. +/ 3: f_lseek() function is removed in addition to 2. */ + + +#define FF_USE_FIND 0 +/* This option switches filtered directory read functions, f_findfirst() and +/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ + + +#define FF_USE_MKFS 0 +/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ + + +#define FF_USE_FASTSEEK 0 +/* This option switches fast seek function. (0:Disable or 1:Enable) */ + + +#define FF_USE_EXPAND 0 +/* This option switches f_expand function. (0:Disable or 1:Enable) */ + + +#define FF_USE_CHMOD 0 +/* This option switches attribute manipulation functions, f_chmod() and f_utime(). +/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ + + +#define FF_USE_LABEL 0 +/* This option switches volume label functions, f_getlabel() and f_setlabel(). +/ (0:Disable or 1:Enable) */ + + +#define FF_USE_FORWARD 0 +/* This option switches f_forward() function. (0:Disable or 1:Enable) */ + + +#define FF_USE_STRFUNC 0 +#define FF_PRINT_LLI 1 +#define FF_PRINT_FLOAT 1 +#define FF_STRF_ENCODE 3 +/* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and +/ f_printf(). +/ +/ 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect. +/ 1: Enable without LF-CRLF conversion. +/ 2: Enable with LF-CRLF conversion. +/ +/ FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2 +/ makes f_printf() support floating point argument. These features want C99 or later. +/ When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character +/ encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE +/ to be read/written via those functions. +/ +/ 0: ANSI/OEM in current CP +/ 1: Unicode in UTF-16LE +/ 2: Unicode in UTF-16BE +/ 3: Unicode in UTF-8 +*/ + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/---------------------------------------------------------------------------*/ + +#define FF_CODE_PAGE 850 +/* This option specifies the OEM code page to be used on the target system. +/ Incorrect code page setting can cause a file open failure. +/ +/ 437 - U.S. +/ 720 - Arabic +/ 737 - Greek +/ 771 - KBL +/ 775 - Baltic +/ 850 - Latin 1 +/ 852 - Latin 2 +/ 855 - Cyrillic +/ 857 - Turkish +/ 860 - Portuguese +/ 861 - Icelandic +/ 862 - Hebrew +/ 863 - Canadian French +/ 864 - Arabic +/ 865 - Nordic +/ 866 - Russian +/ 869 - Greek 2 +/ 932 - Japanese (DBCS) +/ 936 - Simplified Chinese (DBCS) +/ 949 - Korean (DBCS) +/ 950 - Traditional Chinese (DBCS) +/ 0 - Include all code pages above and configured by f_setcp() +*/ + + +#define FF_USE_LFN 3 +#define FF_MAX_LFN 255 +/* The FF_USE_LFN switches the support for LFN (long file name). +/ +/ 0: Disable LFN. FF_MAX_LFN has no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function +/ requires certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and +/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled. +/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can +/ be in range of 12 to 255. It is recommended to be set it 255 to fully support LFN +/ specification. +/ When use stack for the working buffer, take care on stack overflow. When use heap +/ memory for the working buffer, memory management functions, ff_memalloc() and +/ ff_memfree() exemplified in ffsystem.c, need to be added to the project. */ + + +#define FF_LFN_UNICODE 0 +/* This option switches the character encoding on the API when LFN is enabled. +/ +/ 0: ANSI/OEM in current CP (TCHAR = char) +/ 1: Unicode in UTF-16 (TCHAR = WCHAR) +/ 2: Unicode in UTF-8 (TCHAR = char) +/ 3: Unicode in UTF-32 (TCHAR = DWORD) +/ +/ Also behavior of string I/O functions will be affected by this option. +/ When LFN is not enabled, this option has no effect. */ + + +#define FF_LFN_BUF 255 +#define FF_SFN_BUF 12 +/* This set of options defines size of file name members in the FILINFO structure +/ which is used to read out directory items. These values should be sufficient for +/ the file names to read. The maximum possible length of the read file name depends +/ on character encoding. When LFN is not enabled, these options have no effect. */ + + +#define FF_FS_RPATH 0 +/* This option configures support for relative path. +/ +/ 0: Disable relative path and remove related functions. +/ 1: Enable relative path. f_chdir() and f_chdrive() are available. +/ 2: f_getcwd() function is available in addition to 1. +*/ + + +/*---------------------------------------------------------------------------/ +/ Drive/Volume Configurations +/---------------------------------------------------------------------------*/ + +#define FF_VOLUMES 1 +/* Number of volumes (logical drives) to be used. (1-10) */ + + +#define FF_STR_VOLUME_ID 0 +#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" +/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. +/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive +/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each +/ logical drives. Number of items must not be less than FF_VOLUMES. Valid +/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are +/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is +/ not defined, a user defined volume string table is needed as: +/ +/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... +*/ + + +#define FF_MULTI_PARTITION 0 +/* This option switches support for multiple volumes on the physical drive. +/ By default (0), each logical drive number is bound to the same physical drive +/ number and only an FAT volume found on the physical drive will be mounted. +/ When this function is enabled (1), each logical drive number can be bound to +/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() +/ function will be available. */ + + +#define FF_MIN_SS 512 +#define FF_MAX_SS 512 +/* This set of options configures the range of sector size to be supported. (512, +/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and +/ harddisk, but a larger value may be required for on-board flash memory and some +/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured +/ for variable sector size mode and disk_ioctl() function needs to implement +/ GET_SECTOR_SIZE command. */ + + +#define FF_LBA64 0 +/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable) +/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */ + + +#define FF_MIN_GPT 0x10000000 +/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and +/ f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */ + + +#define FF_USE_TRIM 0 +/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) +/ To enable Trim function, also CTRL_TRIM command should be implemented to the +/ disk_ioctl() function. */ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_TINY 0 +/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) +/ At the tiny configuration, size of file object (FIL) is shrinking FF_MAX_SS bytes. +/ Instead of private sector buffer eliminated from the file object, common sector +/ buffer in the filesystem object (FATFS) is used for the file data transfer. */ + + +#define FF_FS_EXFAT 0 +/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) +/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1) +/ Note that enabling exFAT discards ANSI C (C89) compatibility. */ + + +#define FF_FS_NORTC 0 +#define FF_NORTC_MON 1 +#define FF_NORTC_MDAY 1 +#define FF_NORTC_YEAR 2022 +/* The option FF_FS_NORTC switches timestamp feature. If the system does not have +/ an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the +/ timestamp feature. Every object modified by FatFs will have a fixed timestamp +/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. +/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be +/ added to the project to read current time form real-time clock. FF_NORTC_MON, +/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. +/ These options have no effect in read-only configuration (FF_FS_READONLY = 1). */ + + +#define FF_FS_NOFSINFO 0 +/* If you need to know correct free space on the FAT32 volume, set bit 0 of this +/ option, and f_getfree() function at the first time after volume mount will force +/ a full FAT scan. Bit 1 controls the use of last allocated cluster number. +/ +/ bit0=0: Use free cluster count in the FSINFO if available. +/ bit0=1: Do not trust free cluster count in the FSINFO. +/ bit1=0: Use last allocated cluster number in the FSINFO if available. +/ bit1=1: Do not trust last allocated cluster number in the FSINFO. +*/ + + +#define FF_FS_LOCK 0 +/* The option FF_FS_LOCK switches file lock function to control duplicated file open +/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY +/ is 1. +/ +/ 0: Disable file lock function. To avoid volume corruption, application program +/ should avoid illegal open, remove and rename to the open objects. +/ >0: Enable file lock function. The value defines how many files/sub-directories +/ can be opened simultaneously under file lock control. Note that the file +/ lock control is independent of re-entrancy. */ + + +#define FF_FS_REENTRANT 0 +#define FF_FS_TIMEOUT 1000 +/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs +/ module itself. Note that regardless of this option, file access to different +/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs() +/ and f_fdisk() function, are always not re-entrant. Only file/directory access +/ to the same volume is under control of this feature. +/ +/ 0: Disable re-entrancy. FF_FS_TIMEOUT have no effect. +/ 1: Enable re-entrancy. Also user provided synchronization handlers, +/ ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give() +/ function, must be added to the project. Samples are available in ffsystem.c. +/ +/ The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick. +*/ + + + +/*--- End of configuration options ---*/