I have a simple function for testing writing log data to a SD card.
Exact after 1368 time writing (append) a row to the SD card the software locks
and after a hard reset everyting works fine.
I have try this 4 time's and everytime program stops after 1368 time append a string to the SD card.
someone has a suggestion where it goes wrong?
I use controller LPC1549 on a own designed pcb.
Log function locks after 1368 writes (appends) to log file
SDFileSystem sd(SD_MOSI, SD_MISO, SD_SCK, SD_CS, "sd", P1_16, SDFileSystem::SWITCH_NEG_NC, 25000000);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void SendLog(void)
{
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
u08 displayed = false;
time_t seconds = time(NULL);
// create an empty file pointer.
FILE *myLogFile = NULL;
if (!sd.card_present()) { // Make sure a card is present
Display_String(" No card present! ",50,10); // Write string on row 50 and column 10
displayed = false;
for (u08 teller = 52; teller<56; teller++) { // Deze regels clearen
Display_String(" ",teller,10);
}
sd.unmount(); // Unmount the SD card
return;
} else {
Display_String(" Mounting SD card...",50,10); // Write string on row 50 and column 10
if (sd.mount() != 0) { // Mount the filesystem
Display_String("failed to mount the filesystem! ",50,10);
} else {
if(!(displayed)) {
displayed = true;
Display_String(" Mounting OK ",50,10);
//Display the card type
SDFileSystem::CardType cardType = sd.card_type();
if (cardType == SDFileSystem::CARD_NONE)
Display_String("Card type: None",52,10);
else if (cardType == SDFileSystem::CARD_MMC)
Display_String("Card type: MMC ",52,10);
else if (cardType == SDFileSystem::CARD_SD)
Display_String("Card type: SD ",52,10);
else if (cardType == SDFileSystem::CARD_SDHC)
Display_String("Card type: SDHC",52,10);
else
Display_String("Card type: Unknown",52,10);
//Display the card capacity
Display_Value_u32("Sectors: ", sd.disk_sectors(),53,10);
PrintFF("Capacity (MB): ",((float)(sd.disk_sectors())/2048.0),54,10);
}
myLogFile = fopen("/sd/log.txt", "a");
if (myLogFile == NULL) { // check the file is open.
Display_String("failed to open file!",55,10);
myLogFile = fopen("/sd/log.txt", "w");
return;
}
char day[25];
strftime(day, 25,"%Y/%m/%d %a %H:%M:%S",localtime(&seconds)); // Put Year, month, day, weekday, Hour, Minuts, Seconds in string
fprintf(myLogFile,"\r\n%s %010lu %d %d %d ",day,test.ErrorStatus,200,300,400); // write string, counter (test.Errorstatus) and 3 numbers on the SD card
fclose( myLogFile); // Close logfile
}
}
sd.unmount(); // Unmount the SD card
}
Here's a crude example of how to modify my library for DMA support:
SDFileSystem.cpp
And there you have it! This code is written for the LPC1549, but it should be fairly easy to modify for other targets. It uses the official rtos library to sleep the calling thread while data transfer takes place (so accessing the SD card from ISR context is not allowed).
At this point, I don't have any plans to bake DMA support into the library since I don't feel like building my own lightweight HAL layer and keeping up with new targets as they're added. The best way to do this would be if the mbed library provided a non-blocking API for reading/writing from the SPI bus, and hid the actually implementation from the user. Something like the following would work (with a bit of additional template magic of course):
Targets with a DMA controller would use it to perform the transfer, while targets without a DMA controller could use interrupts. The important point here is that the transfer takes place in the background, using a microcontroller-independent non-blocking API. This could be extended to other busses as well, such as I2C or Serial. If there's enough support for this kind of API, I may be persuaded to create a separate thread to work on getting it added.