Important update: Arm Announces End of Life Timeline for Mbed. This site will be archived in July 2026. Read the full announcement.
Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
Fopen not opening/creating files on SD card
Zoltan Hudak.
9
replies
Hello Denwis,
Try to modify your code as below:
...
// fs.mount(&sd);
// // Check if file was opened for some reason
// if(fp != NULL)
// {
// pc.printf("File was opened, closing it\n\r");
// fclose(fp);
// }
// fp = fopen("/sd/mytest/sdtest.txt", "w");
// if(fp == NULL) {
// pc.printf("Could not open file for write\n\r");
// }
// fprintf(fp, "Hello fun SD Card World!");
// for (int i = 0; i < 20; i++){
// printf("Writing decimal numbers to a file (%d/20)\r\n", i);
// fprintf(fp, "%d\r\n", i);
// }
// pc.printf("Writing decimal numbers to a file (20/20) done.\r\n");
// pc.printf("Closing file.\n\r");
// fclose(fp);
// return 0;
int err = fs.mount(&sd);
pc.printf("%s\r\n", (err ? "Failed :(\r\n" : "OK\r\n"));
if (err)
return err;
// Open the file.
pc.printf("Opening file '/sd/mytest/sdtest.txt'... ");
fp = fopen("/sd/mytest/sdtest.txt", "w+");
pc.printf("%s\r\n", (!fp ? "Failed :(\r\n" : "OK\r\n"));
if (!fp)
{
// Check whether directory '/sd/mytest' exists.
pc.printf("\r\nChecking directory '/sd/mytest'...\r\n");
struct stat info;
err = stat("/sd/mytest", &info);
if (err)
{
pc.printf("Directory '/sd/mytest' does not exist.\r\n");
pc.printf("Trying to create it...");
err = mkdir("/sd/mytest", 0777);
pc.printf("%s\r\n", (err ? "Failed :(\r\n" : "OK\r\n"));
if (err)
return err;
}
// Create a new 'sdtest.txt' file.
pc.printf("File not found, creating a new one...\r\n");
fp = fopen("/sd/mytest/sdtest.txt", "w+");
pc.printf("%s\r\n", (!fp ? "Failed :(" : "OK"));
if (!fp)
{
error("error: %s (%d)\r\n", strerror(errno), -errno);
return errno;
}
}
for (int i = 0; i < 10; i++)
{
pc.printf("Writing numbers (%d/%d)... ", i, 10);
err = fprintf(fp, " %d\r\n", i);
if (err < 0)
{
pc.printf("Fail :(\r\n");
error("error: %s (%d)\r\n", strerror(errno), -errno);
}
else
pc.printf("OK\r\n");
}
pc.printf("Writing numbers (%d/%d)... OK\r\n\r\n", 10, 10);
err = fclose(fp);
pc.printf("Closing file '/sd/mytest/sdtest.txt'... ");
pc.printf("%s\r\n", (err ? "Failed :(\r\n" : "OK\r\n"));
if (err)
return err;
return 0;
- Before using it remember to format your SD card for the FAT file system for example with the SD Formatter utility.
- To test the code above I have connected an SD card to my mbed board according to this schematic and it worked fine.
Thanks for your input,
I get errors saying " Error: Incomplete type is not allowed "struct stat info;"" " Error: Incomplete type is not allowed "err = stat("/sd/mytest", &info);"" Am I missing a library for stat?
If it helps, I am using mbed os version 5.5.7 for mDot uses.
I double checked my SD card and it is in FAT32 format. I formatted it again just in case.
This is what I'm following for my SD card breakout board

MOSI - 11 - Green, MISO - 12 - Red, CLK - 13 - Yellow, CS - 8 - Blue
I have tested the code with mbed-os- 5.7.7:
- The data type
struct statand functionint stat(const char *path, struct stat *st)are declared in theplatform/mbed-retarget.hfile of the mbed-os library. - The
int stat(const char *path, struct stat *st)function is defined inplatform/mbed-retarget.cppfile of the mbed-os library.
Unfortunately it seems that older versions do not include stat support. In such case I would recommend to either create the /sdtest directory in advance on a PC or to simply use the SD card root directory instead of the /sdtest one.
There is mismatch between the code and wiring:
- The CS signal supposed to be connected to pin D10
SDBlockDevice sd(D11, D12, D13, D10); // mosi, miso, sclk, cs
- However, on the picture above it is connected to pin D8.
Ok I've created my own struct stat as shown below.
Now the problem is that mount() never exits.
I have my signals at the correct pins. Sorry it wasn't clear that the signals I gave were to show which wires came from which pin on the arduino, which I used as a guide to how I should wire my SD card breakout board.
EDIT: Nevermind, it does exit mount() and outputs "Failed :(" after a very long time but it doesn't go anywhere else after. Added the sd card code you provided.
stat
#include "platform/FilePath.h"
// For struct stat
typedef unsigned int dev_t; ///< Device ID type
typedef unsigned long ino_t; ///< File serial number
typedef unsigned int nlink_t; ///< Number of links to a file
typedef unsigned int uid_t; ///< User ID
typedef unsigned int gid_t; ///< Group ID
typedef signed long off_t; ///< Offset in a data stream
struct mbed::stat {
dev_t st_dev; ///< Device ID containing file
ino_t st_ino; ///< File serial number
mode_t st_mode; ///< Mode of file
nlink_t st_nlink; ///< Number of links to file
uid_t st_uid; ///< User ID
gid_t st_gid; ///< Group ID
off_t st_size; ///< Size of file in bytes
time_t st_atime; ///< Time of last access
time_t st_mtime; ///< Time of last data modification
time_t st_ctime; ///< Time of last status change
};
int mystat(const char *path, struct stat *st) {
FilePath fp(path);
FileSystemHandle *fs = fp.fileSystem();
if (fs == NULL) {
errno = ENODEV;
return -1;
}
int err = fs->stat(fp.fileName(), st);
if (err < 0) {
errno = -err;
return -1;
} else {
return 0;
}
}
sdCardTest
int err = fs.mount(&sd);
pc.printf("%s\r\n", (err ? "Failed :(\r\n" : "OK\r\n"));
if (err)
return err;
pc.printf("Error for mounting was %d\n\r", err);
// Open the file.
pc.printf("Opening file '/sd/mytest/sdtest.txt'... ");
fp = fopen("/sd/mytest/sdtest.txt", "w+");
pc.printf("%s\r\n", (!fp ? "Failed :(\r\n" : "OK\r\n"));
if (!fp)
{
// Check whether directory '/sd/mytest' exists.
pc.printf("\r\nChecking directory '/sd/mytest'...\r\n");
struct stat info;
err = mystat("/sd/mytest", &info);
if (err)
{
pc.printf("Directory '/sd/mytest' does not exist.\r\n");
pc.printf("Trying to create it...");
err = mkdir("/sd/mytest", 0777);
pc.printf("%s\r\n", (err ? "Failed :(\r\n" : "OK\r\n"));
if (err)
return err;
}
// Create a new 'sdtest.txt' file.
pc.printf("File not found, creating a new one...\r\n");
fp = fopen("/sd/mytest/sdtest.txt", "w+");
pc.printf("%s\r\n", (!fp ? "Failed :(" : "OK"));
if (!fp)
{
error("error: %s (%d)\r\n", strerror(errno), -errno);
return errno;
}
}
for (int i = 0; i < 10; i++)
{
pc.printf("Writing numbers (%d/%d)... ", i, 10);
err = fprintf(fp, " %d\r\n", i);
if (err < 0)
{
pc.printf("Fail :(\r\n");
error("error: %s (%d)\r\n", strerror(errno), -errno);
}
else
pc.printf("OK\r\n");
}
pc.printf("Writing numbers (%d/%d)... OK\r\n\r\n", 10, 10);
err = fclose(fp);
pc.printf("Closing file '/sd/mytest/sdtest.txt'... ");
pc.printf("%s\r\n", (err ? "Failed :(\r\n" : "OK\r\n"));
if (err)
return err;
return 0;
The reason why mount fails could be that the lowest SPI frequency of your mbed board is higher than 100 kHz, so the SD card is not getting initialized properly.
See https://os.mbed.com/forum/bugs-suggestions/topic/27511/
According to the sd-driver library, the most current version, sd-driver-0.1.2, uses mbed-os-5.6.1, and I am now using mbed-os-5.7.4 which the current mdot-3.1.0 uses. This now allows me to use struct stat without problems.
According to that bug topic, I've tried to look for what my board's minimum frequency is and I am having trouble looking for it. I've looked at targets/TARGET_STM/TARGET_STM32F4/spi_api.c and it has a function to get spi frequency, so I think I can pass a SPI object to it to find my minimum frequency. My device is actually 96MHz according to this information: https://os.mbed.com/platforms/MTS-mDot-F411/ but I can't find what the lowesit SPI frequency is.
I also found this topic: https://os.mbed.com/teams/ST/wiki/SPI-output-clock-frequency and I think that it might help me figure out what I should change the default frequency to, but I am confused as to find which SPI_1 or SPI_2.....and from there I am lost.
Everything works now. I think it was the microSD card to SD card adapter that was the problem. I got a new SD card which is a SanDisk 8GB SDHC card, and it worked perfectly once I put it in the breakout board.
No need to change the default spi frequency in the sd-driver library.
Using mbed version 5.7.4.
Hello I'm back.
So sd card is not working again. It is very inconsistent as I've tried 2 different FAT32 formatted sd cards.
This was my process:
I wired the breakout board to an arduino with the same wiring schematics as I've posted before. I tried 6 different sd cards to see which ones were being read correctly. I formatted the cards and 2 were showing files and folders consistently 10/10 tries so I thought they would work when I wire the breakout board to my mDot.
I wire the sd card reader breakout board to my mDot and upload my mbed code to it and it worked initializing, mounting, and creating directory and file. Great. Then I reset my mDot and it initializes and mounts successfully and tries to open the newly created file, but it then just freezes there. I reset again, and it does the same thing.
I then decide to delete the created folder from my PC and put the sd card back to the sd card reader breakout board. This time, it freezes in the initializing stage. I tried again with my other SD card that worked when trying on arduino and it did the same thing, freezes in initializing line.
I wire the breakout board to the arduino again and it reads everything consistently. I don't think it's the breakout board, or the breadbaord, or the wiring. I also tried to use the sd-driver-hs version but that doesn't work either.
I've tried to use SDFileSystem that some people have changed and they don't work. At this point, could it be my mDot? Maybe the high frequency with SPI. Mind you I am using the online compiler. I tried to import ARM's sd-driver 1.2 from github to the online compiler and still same results. I've been using the sd-driver library that is available from the online compiler import function.
I do not use mDot so I'm not able to verify whether it could interfere with the sd-driver. Just a few tips:
- I was recently struggling with a faulty SD card slot too. So I think it's a good idea to test also the slot with Arduino before using it in mbed application.
- Make sure that each file in your code was closed before removing the SD card from a slot.
- Try to simplify your program as much as possible to see which part could cause the problem.
Hi,
So I am trying to create an unexisting text file in my SD card and I am unable to fopen my path or file. I am using this SD card breakout from sparkfun: https://www.sparkfun.com/products/12941
My init() function for the Blockdevice is successful.
I've tried to use the SDFileSystem library but apparently it isn't supported anymore: https://os.mbed.com/questions/77743/stm32f769NI-SDFileSystem-Error/
I'm using a microSD card adapter. I don't know if this may be causing the errors and I am using a mDot.
And I am following along this code: https://os.mbed.com/teams/University-of-Plymouth-Stage-2-and-3/code/ELEC350-SD_Card_Demo/file/528e42a15d44/main.cpp/
Thanks.
SDCardTest
#include <mbed.h> #include "SDBlockDevice.h" #include "FATFileSystem.h" SDBlockDevice sd(D11, D12, D13, D10); // mosi, miso, sclk, cs FATFileSystem fs("sd"); static uint8_t network_address[] = { 0x00, 0x11, 0x22, 0x33 }; static uint8_t network_session_key[] = { 0x00, 0x11, 0x22, 0x33, 0x00, 0x11, 0x22, 0x33, 0x00, 0x11, 0x22, 0x33, 0x00, 0x11, 0x22, 0x33 }; static uint8_t data_session_key[] = { 0x33, 0x22, 0x11, 0x00, 0x33, 0x22, 0x11, 0x00, 0x33, 0x22, 0x11, 0x00, 0x33, 0x22, 0x11, 0x00 }; mDot* dot = NULL; lora::ChannelPlan* plan = NULL; Serial pc(USBTX, USBRX); /* * Variables used for mDot */ uint32_t tx_frequency; uint8_t tx_datarate; uint8_t tx_power; uint8_t frequency_band; void return_error(int ret_val){ if (ret_val) printf("Failure. %d\r\n", ret_val); else printf("done.\r\n"); } void errno_error(void* ret_val){ if (ret_val == NULL) printf(" Failure. %d \r\n", ret_val); else printf(" done.\r\n"); } int main(void) { // Custom event handler for automatically displaying RX data //interruptEverything.attach(&interruptReadTemperature, 7.0); RadioEvent events; // Change baud rate in serial terminal to this value pc.baud(115200); FILE *fp; mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL); plan = new lora::ChannelPlan_US915(); logInfo("Now asserting"); assert(plan); dot = mDot::getInstance(plan); assert(dot); logInfo("mbed-os library version: %d", MBED_LIBRARY_VERSION); // start from a well-known state logInfo("defaulting Dot configuration"); dot->resetConfig(); // make sure library logging is turned on dot->setLogLevel(mts::MTSLog::INFO_LEVEL); // attach the custom events handler dot->setEvents(&events); // update configuration if necessary if (dot->getJoinMode() != mDot::PEER_TO_PEER) { logInfo("changing network join mode to PEER_TO_PEER"); if (dot->setJoinMode(mDot::PEER_TO_PEER) != mDot::MDOT_OK) { logError("failed to set network join mode to PEER_TO_PEER"); } } frequency_band = dot->getFrequencyBand(); switch (frequency_band) { case lora::ChannelPlan::EU868_OLD: case lora::ChannelPlan::EU868: // 250kHz channels achieve higher throughput // DR_6 : SF7 @ 250kHz // DR_0 - DR_5 (125kHz channels) available but much slower tx_frequency = 869850000; tx_datarate = lora::DR_6; // the 869850000 frequency is 100% duty cycle if the total power is under 7 dBm - tx power 4 + antenna gain 3 = 7 tx_power = 4; break; case lora::ChannelPlan::US915_OLD: case lora::ChannelPlan::US915: case lora::ChannelPlan::AU915_OLD: case lora::ChannelPlan::AU915: // 500kHz channels achieve highest throughput // DR_8 : SF12 @ 500kHz // DR_9 : SF11 @ 500kHz // DR_10 : SF10 @ 500kHz // DR_11 : SF9 @ 500kHz // DR_12 : SF8 @ 500kHz // DR_13 : SF7 @ 500kHz // DR_0 - DR_3 (125kHz channels) available but much slower tx_frequency = 915500000; tx_datarate = lora::DR_13; // 915 bands have no duty cycle restrictions, set tx power to max tx_power = 20; break; case lora::ChannelPlan::AS923: case lora::ChannelPlan::AS923_JAPAN: // 250kHz channels achieve higher throughput // DR_6 : SF7 @ 250kHz // DR_0 - DR_5 (125kHz channels) available but much slower tx_frequency = 924800000; tx_datarate = lora::DR_6; tx_power = 16; break; case lora::ChannelPlan::KR920: // DR_5 : SF7 @ 125kHz tx_frequency = 922700000; tx_datarate = lora::DR_5; tx_power = 14; break; default: while (true) { logFatal("no known channel plan in use - extra configuration is needed!"); wait(5); } break; } // in PEER_TO_PEER mode there is no join request/response transaction // as long as both Dots are configured correctly, they should be able to communicate update_peer_to_peer_config(network_address, network_session_key, data_session_key, tx_frequency, tx_datarate, tx_power); // save changes to configuration logInfo("saving configuration"); if (!dot->saveConfig()) { logError("failed to save configuration"); } // Display configuration // It's gonna output a lot of information onto the Serial Terminal display_config(); //mkdir("/sd/mytest/", 0777); int error = 0; if ( 0 == sd.init()) { printf("Init success \n\r"); } fs.mount(&sd); // Check if file was opened for some reason if(fp != NULL) { pc.printf("File was opened, closing it\n\r"); fclose(fp); } fp = fopen("/sd/mytest/sdtest.txt", "w"); if(fp == NULL) { pc.printf("Could not open file for write\n\r"); } fprintf(fp, "Hello fun SD Card World!"); for (int i = 0; i < 20; i++){ printf("Writing decimal numbers to a file (%d/20)\r\n", i); fprintf(fp, "%d\r\n", i); } pc.printf("Writing decimal numbers to a file (20/20) done.\r\n"); pc.printf("Closing file.\n\r"); fclose(fp); return 0; }