Duggle Posted June 25, 2012 Report Share Posted June 25, 2012 I'm using a core32 to log data from environmental sensors. I'm concerned that writing 100bytes to a file every few seconds would result in the modification to the SD card's file allocation table (FAT) that over time may cause it to fail. As a result I've made my logging code so that it caches the log records and writes them in one pass 10kbytes at a time. I have the core hooked up with an analog input monitoring a signal derived from the 12V pre-regulated supply. If the power fails (or is switched off) the falling voltage is detected and the cache is written to disk followed by a call to FILE_WriteClose() . My assumption is that the FAT is only modified when the FILE_WriteClose() is called. I havn't looked at the filesystem code underlying the midibox FILE module, so my questions are: Does the SD card have inbuilt wear leveling? Does my strategy of write caching help the situation? Assuming I'm writing lots of data over time what is the best strategy for getting maximum life fro m the SD Card? Quote Link to comment Share on other sites More sharing options...
Hawkeye Posted June 25, 2012 Report Share Posted June 25, 2012 (edited) Interesting topic and usecase for a core32 :) The SD standard does not specify wear levelling, but there are manufacturers, that explicitly provide it: http://www.memorydep...t.asp?catid=isd Using such a 2 GB card, one would have to write 10 TB of data, before it becomes unusable. So I would buy an "industrial" one and not worry too much about optimizing/caching on the software side. Bye, Peter Edited June 25, 2012 by Hawkeye Quote Link to comment Share on other sites More sharing options...
Duggle Posted June 25, 2012 Author Report Share Posted June 25, 2012 Industrial strength sounds like a good idea in any case! I suppose if FILE_WriteClose() results in a change to the FAT table then the caching which I've written and somewhat tested would result in a x100 reduction in "wear" in the scenario I described. So whilst the application can afford 10k of RAM I guess I'll keep it in. Here's the code: #define db MIOS32_MIDI_SendDebugMessage /* * DataLog.c * * Created on: 21/06/2012 * Author: Dug */ #include <mios32.h> #include <FreeRTOS.h> #include <task.h> #include <semphr.h> #include "file.h" #include <string.h> #include "debug.h" #define CACHE_SIZE 10000 u32 DataLog_Index; u8 DataLog_Cache[CACHE_SIZE]; xSemaphoreHandle DataLog_Mutex; u8 DataLog_Held; void CacheCommit(); void DataLog_Init(){ if(DataLog_Mutex==NULL) DataLog_Mutex=xSemaphoreCreateMutex(); xSemaphoreTake(DataLog_Mutex,portMAX_DELAY); DataLog_Index=0; //start of cache xSemaphoreGive(DataLog_Mutex); } void DataLog_AddLine(char* s){ //cache null terminated string char eol[3]="\r\n"; //Windows compatable EOL xSemaphoreTake(DataLog_Mutex,portMAX_DELAY); db("AddLine:%s",s); if ((strlen(s)+3+DataLog_Index)>CACHE_SIZE){ CacheCommit(); //cache now empty db("cache comitted."); } strcpy((char*)&DataLog_Cache[DataLog_Index],s); strcat((char*)&DataLog_Cache[DataLog_Index],eol); db("line cached:%s",&DataLog_Cache[DataLog_Index]); DataLog_Index+=strlen(s)+2; //include eol but not null xSemaphoreGive(DataLog_Mutex); } void CacheCommit(){ //only called from these functions s32 r=FILE_FileExists("DataLog.txt"); switch(r){ case 0: FILE_WriteOpen("DataLog.txt",1); //create new db("DataLog Create"); break;//create case 1: FILE_WriteOpen("DataLog.txt",0); //re-open existing db("DataLog Append"); break; default:db("Datalog.txt problem");return; } FILE_WriteSeek(FILE_WriteGetCurrentSize()); FILE_WriteBuffer(DataLog_Cache,DataLog_Index); DataLog_Index=0; FILE_WriteClose(); } void DataLog_Commit(){ //write cache physical sd card xSemaphoreTake(DataLog_Mutex,portMAX_DELAY); CacheCommit(); xSemaphoreGive(DataLog_Mutex); } void DataLog_HoldSafe(){ //commit to disk but don't release mutex (we've lost power) if (DataLog_Mutex&&(DataLog_Held==0)){ //only if DataLog has been initializied xSemaphoreTake(DataLog_Mutex,portMAX_DELAY); //take but don't release DataLog_Held=1; CacheCommit(); } } void DataLog_UnHold(){ //power back up so release logging for use by tasks if (DataLog_Held){ xSemaphoreGive(DataLog_Mutex); //release mutex now DataLog_Held=0; } } void DataLog_PrintFile(){ file_t F; char s[120]=""; u8 b[2]={0,0}; xSemaphoreTake(DataLog_Mutex,portMAX_DELAY); if (FILE_ReadOpen(&F,"DataLog.txt")<0){ db("DataLog_Printfile problem"); xSemaphoreGive(DataLog_Mutex); return; } while(FILE_ReadByte(&b[0])>=0){ //read until EOF if(b[0]=='\r')continue; if(b[0]=='\n'){ b[0]=0; strcat(s,(char*)b); //null terminate db("->%s<-",(char*)s); //print line strcpy(s,""); //reset }else strcat(s,(char*)b); //add char } FILE_ReadClose(&F); xSemaphoreGive(DataLog_Mutex); } Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.