Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
SnSDUtils.cpp@10:3c93db1cfb12, 2012-08-10 (annotated)
- Committer:
- uci1
- Date:
- Fri Aug 10 18:35:43 2012 +0000
- Revision:
- 10:3c93db1cfb12
- Parent:
- 8:95a325df1f6b
- Child:
- 12:d472f9811262
Ensure that lockRegisters (p20) is 0 before accessing the SD card, for example when closing the file. This fixes an issue seen when running in power count mode. Communications still under dev. Many debug outputs.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
uci1 | 0:664899e0b988 | 1 | #include "SnSDUtils.h" |
uci1 | 0:664899e0b988 | 2 | |
uci1 | 0:664899e0b988 | 3 | #include "mbed.h" |
uci1 | 0:664899e0b988 | 4 | #include "SDFileSystem.h" |
uci1 | 0:664899e0b988 | 5 | #include <string.h> |
uci1 | 0:664899e0b988 | 6 | |
uci1 | 0:664899e0b988 | 7 | #include "SnConfigFrame.h" |
uci1 | 0:664899e0b988 | 8 | #include "SnEventFrame.h" |
uci1 | 0:664899e0b988 | 9 | |
uci1 | 0:664899e0b988 | 10 | |
uci1 | 1:e392595b4b76 | 11 | const char* const SnSDUtils::kSDsubDir = "/sd"; |
uci1 | 2:e67f7c158087 | 12 | char SnSDUtils::fgCurFileName[kFNBufSize]={0}; |
uci1 | 1:e392595b4b76 | 13 | FILE* SnSDUtils::fgCurFile = 0; |
uci1 | 8:95a325df1f6b | 14 | const uint8_t SnSDUtils::kIOvers = 3; |
uci1 | 5:9cea89700c66 | 15 | const uint32_t SnSDUtils::kMaxSizeOfFileHdr = |
uci1 | 5:9cea89700c66 | 16 | sizeof(uint8_t)+sizeof(uint64_t)+sizeof(uint32_t)+sizeof(uint16_t) |
uci1 | 8:95a325df1f6b | 17 | +(sizeof(uint8_t)+(2u*sizeof(uint16_t))); // power frame v1 |
uci1 | 4:a91682e19d6b | 18 | |
uci1 | 4:a91682e19d6b | 19 | static const uint16_t __kMaxUShort = ~0; |
uci1 | 0:664899e0b988 | 20 | |
uci1 | 0:664899e0b988 | 21 | const char* SnSDUtils::GetOutFileName(const uint64_t macadr, |
uci1 | 0:664899e0b988 | 22 | const uint32_t run, |
uci1 | 0:664899e0b988 | 23 | const uint16_t seq) { |
uci1 | 0:664899e0b988 | 24 | // returns the formatted file name, or NULL if the directory is too long |
uci1 | 0:664899e0b988 | 25 | // and the full name cannot fit in the buffer |
uci1 | 0:664899e0b988 | 26 | // NOTE: this fcn uses a static buffer, and so should not be called |
uci1 | 0:664899e0b988 | 27 | // multiple times in the same line (that includes the calling of functions |
uci1 | 0:664899e0b988 | 28 | // that call this function!) |
uci1 | 0:664899e0b988 | 29 | // |
uci1 | 0:664899e0b988 | 30 | // filename = SnEvtsM[6-byte hex mac adr]r[6-digit run num]s[5-digit seq num].dat |
uci1 | 0:664899e0b988 | 31 | // 35 chars 7 + 12 +1+ 5 +1+ 5 + 4 |
uci1 | 0:664899e0b988 | 32 | |
uci1 | 0:664899e0b988 | 33 | if (strlen(kSDsubDir)<(kFNBufSize-37)) { |
uci1 | 0:664899e0b988 | 34 | static char tbuf[kFNBufSize]; |
uci1 | 0:664899e0b988 | 35 | memset(tbuf, 0, sizeof(char)*kFNBufSize); |
uci1 | 0:664899e0b988 | 36 | // if file name format changes, GetSeqNum must be changed too |
uci1 | 0:664899e0b988 | 37 | sprintf(tbuf, "%s/SnEvtsM%012llXr%05ds%05d.dat", |
uci1 | 0:664899e0b988 | 38 | kSDsubDir, |
uci1 | 0:664899e0b988 | 39 | macadr>>16, // 64 -> 48 bits |
uci1 | 0:664899e0b988 | 40 | run, seq); |
uci1 | 0:664899e0b988 | 41 | return tbuf; |
uci1 | 0:664899e0b988 | 42 | } else { |
uci1 | 0:664899e0b988 | 43 | return NULL; |
uci1 | 0:664899e0b988 | 44 | } |
uci1 | 0:664899e0b988 | 45 | } |
uci1 | 0:664899e0b988 | 46 | |
uci1 | 10:3c93db1cfb12 | 47 | uint16_t SnSDUtils::GetCurSeqNum() { |
uci1 | 10:3c93db1cfb12 | 48 | return GetSeqNumFromFileName(fgCurFileName); |
uci1 | 10:3c93db1cfb12 | 49 | } |
uci1 | 10:3c93db1cfb12 | 50 | |
uci1 | 10:3c93db1cfb12 | 51 | uint16_t SnSDUtils::GetSeqNumFromFileName(const char* fn) { |
uci1 | 10:3c93db1cfb12 | 52 | uint16_t seq=0; |
uci1 | 10:3c93db1cfb12 | 53 | const uint32_t ncomp = strrchr(fn, 's') - fn; |
uci1 | 10:3c93db1cfb12 | 54 | if (ncomp<strlen(fn)) { |
uci1 | 10:3c93db1cfb12 | 55 | sscanf(fn+ncomp,"s%hu.dat",&seq); |
uci1 | 10:3c93db1cfb12 | 56 | } |
uci1 | 10:3c93db1cfb12 | 57 | return seq; |
uci1 | 10:3c93db1cfb12 | 58 | } |
uci1 | 10:3c93db1cfb12 | 59 | |
uci1 | 0:664899e0b988 | 60 | uint16_t SnSDUtils::GetSeqNum(const uint64_t macadr, |
uci1 | 0:664899e0b988 | 61 | const uint32_t run) { |
uci1 | 0:664899e0b988 | 62 | // count the files having expected filename format |
uci1 | 0:664899e0b988 | 63 | |
uci1 | 0:664899e0b988 | 64 | const char* fn = GetOutFileName(macadr, run, 0) |
uci1 | 0:664899e0b988 | 65 | + strlen(kSDsubDir) + 1; // take out dir and '/'s |
uci1 | 0:664899e0b988 | 66 | |
uci1 | 0:664899e0b988 | 67 | DIR* d; |
uci1 | 0:664899e0b988 | 68 | struct dirent* dent; |
uci1 | 0:664899e0b988 | 69 | |
uci1 | 6:6f002d202f59 | 70 | uint16_t seq=0, newseq=0; |
uci1 | 0:664899e0b988 | 71 | if ( (d = opendir( kSDsubDir ))!=NULL ) { |
uci1 | 0:664899e0b988 | 72 | // don't compare seq#. don't use num of chars in case seq is >999 |
uci1 | 0:664899e0b988 | 73 | const uint32_t ncomp = strrchr(fn, 's') - fn; |
uci1 | 0:664899e0b988 | 74 | while ( (dent = readdir(d))!=NULL ) { |
uci1 | 0:664899e0b988 | 75 | if (strncmp(dent->d_name, fn, ncomp)==0) { |
uci1 | 6:6f002d202f59 | 76 | // allow for deleted files to make gaps. |
uci1 | 6:6f002d202f59 | 77 | // search for highest seq number and increase that |
uci1 | 7:079617408fec | 78 | sscanf((dent->d_name)+ncomp,"s%hu.dat",&seq); |
uci1 | 7:079617408fec | 79 | /* |
uci1 | 7:079617408fec | 80 | printf("dn=%s, seq=%hu, __kMaxUShort=%hu\r\n", |
uci1 | 7:079617408fec | 81 | dent->d_name, seq, __kMaxUShort); |
uci1 | 7:079617408fec | 82 | */ |
uci1 | 4:a91682e19d6b | 83 | if (seq==__kMaxUShort) { |
uci1 | 6:6f002d202f59 | 84 | newseq = seq; |
uci1 | 6:6f002d202f59 | 85 | break; |
uci1 | 6:6f002d202f59 | 86 | } |
uci1 | 6:6f002d202f59 | 87 | if (seq>=newseq) { |
uci1 | 6:6f002d202f59 | 88 | newseq=seq+1; |
uci1 | 6:6f002d202f59 | 89 | } |
uci1 | 6:6f002d202f59 | 90 | if (newseq==__kMaxUShort) { |
uci1 | 4:a91682e19d6b | 91 | break; |
uci1 | 4:a91682e19d6b | 92 | } |
uci1 | 0:664899e0b988 | 93 | } |
uci1 | 0:664899e0b988 | 94 | } |
uci1 | 0:664899e0b988 | 95 | closedir(d); |
uci1 | 0:664899e0b988 | 96 | } |
uci1 | 7:079617408fec | 97 | |
uci1 | 6:6f002d202f59 | 98 | return newseq; |
uci1 | 0:664899e0b988 | 99 | } |
uci1 | 0:664899e0b988 | 100 | |
uci1 | 3:24c5f0f50bf1 | 101 | FILE* SnSDUtils::OpenExistingFile(const char* name, const bool setcurrent) { |
uci1 | 0:664899e0b988 | 102 | FILE* f = 0; |
uci1 | 0:664899e0b988 | 103 | if (name!=NULL) { |
uci1 | 3:24c5f0f50bf1 | 104 | f = OpenSDFile(name, "rb"); |
uci1 | 3:24c5f0f50bf1 | 105 | if (setcurrent) { |
uci1 | 3:24c5f0f50bf1 | 106 | fgCurFile = f; |
uci1 | 3:24c5f0f50bf1 | 107 | } |
uci1 | 0:664899e0b988 | 108 | } |
uci1 | 0:664899e0b988 | 109 | return f; |
uci1 | 0:664899e0b988 | 110 | } |
uci1 | 0:664899e0b988 | 111 | |
uci1 | 3:24c5f0f50bf1 | 112 | FILE* SnSDUtils::OpenSDFile(const char* name, const char* mode) { |
uci1 | 3:24c5f0f50bf1 | 113 | FILE* f = fopen(name, mode); |
uci1 | 1:e392595b4b76 | 114 | //setvbuf(f, 0, _IONBF, 0); // no buffering |
uci1 | 1:e392595b4b76 | 115 | return f; |
uci1 | 1:e392595b4b76 | 116 | } |
uci1 | 1:e392595b4b76 | 117 | |
uci1 | 0:664899e0b988 | 118 | FILE* SnSDUtils::OpenNewOutputFile(const uint64_t macadr, |
uci1 | 8:95a325df1f6b | 119 | const uint32_t run) { |
uci1 | 0:664899e0b988 | 120 | // opens a new file in the specified directory and writes this |
uci1 | 0:664899e0b988 | 121 | // this mbed's mac address as the first sizeof(uint64_t) bytes (i.e. 4 bytes) |
uci1 | 0:664899e0b988 | 122 | // |
uci1 | 0:664899e0b988 | 123 | const uint16_t seq = GetSeqNum(macadr, run); |
uci1 | 0:664899e0b988 | 124 | memset(fgCurFileName, 0, sizeof(char)*kFNBufSize); |
uci1 | 2:e67f7c158087 | 125 | strncpy(fgCurFileName,GetOutFileName(macadr, run, seq),kFNBufSize-1); |
uci1 | 0:664899e0b988 | 126 | //fprintf(stderr,"cur file = %s (%hu)\n\r",fgCurFileName,seq); |
uci1 | 1:e392595b4b76 | 127 | fgCurFile = 0; |
uci1 | 0:664899e0b988 | 128 | if (fgCurFileName!=NULL) { |
uci1 | 3:24c5f0f50bf1 | 129 | fgCurFile = OpenSDFile(fgCurFileName, "wb"); |
uci1 | 2:e67f7c158087 | 130 | if (fgCurFile!=NULL && ferror(fgCurFile)==0) { |
uci1 | 8:95a325df1f6b | 131 | WriteFileHeader(fgCurFile, macadr, run, seq); |
uci1 | 2:e67f7c158087 | 132 | } |
uci1 | 0:664899e0b988 | 133 | } |
uci1 | 1:e392595b4b76 | 134 | return fgCurFile; |
uci1 | 0:664899e0b988 | 135 | } |
uci1 | 0:664899e0b988 | 136 | |
uci1 | 0:664899e0b988 | 137 | bool SnSDUtils::WriteEventTo(FILE* efile, char* const evtBuf, |
uci1 | 0:664899e0b988 | 138 | const SnEventFrame& evt, |
uci1 | 0:664899e0b988 | 139 | const SnConfigFrame& conf) { |
uci1 | 0:664899e0b988 | 140 | // write event to SD card |
uci1 | 0:664899e0b988 | 141 | |
uci1 | 0:664899e0b988 | 142 | uint8_t sLoseLSB=0, sLoseMSB=0; |
uci1 | 0:664899e0b988 | 143 | uint16_t sWvBase=0; |
uci1 | 0:664899e0b988 | 144 | conf.GetPackParsFor(SnConfigFrame::kSDcard, sLoseLSB, sLoseMSB, sWvBase); |
uci1 | 8:95a325df1f6b | 145 | SnHeaderFrame::WriteTo(efile, SnHeaderFrame::kEventCode, |
uci1 | 8:95a325df1f6b | 146 | evt.SizeOf(SnEventFrame::kIOVers, sLoseLSB, sLoseMSB)); |
uci1 | 0:664899e0b988 | 147 | const bool ret = evt.WriteTo(efile, evtBuf, sLoseLSB, sLoseMSB, sWvBase); |
uci1 | 0:664899e0b988 | 148 | fflush(efile); |
uci1 | 0:664899e0b988 | 149 | return ret; |
uci1 | 0:664899e0b988 | 150 | } |
uci1 | 0:664899e0b988 | 151 | |
uci1 | 0:664899e0b988 | 152 | bool SnSDUtils::WriteConfig(FILE* efile, |
uci1 | 0:664899e0b988 | 153 | const SnConfigFrame& conf) { |
uci1 | 8:95a325df1f6b | 154 | SnHeaderFrame::WriteTo(efile, SnHeaderFrame::kConfigCode, |
uci1 | 8:95a325df1f6b | 155 | conf.SizeOf(SnConfigFrame::kIOVers)); |
uci1 | 0:664899e0b988 | 156 | conf.WriteTo(efile); |
uci1 | 0:664899e0b988 | 157 | return true; |
uci1 | 0:664899e0b988 | 158 | } |
uci1 | 0:664899e0b988 | 159 | |
uci1 | 0:664899e0b988 | 160 | void SnSDUtils::DeleteFile(FILE*& f, const char* fname) { |
uci1 | 0:664899e0b988 | 161 | fclose(f); |
uci1 | 0:664899e0b988 | 162 | f=0; |
uci1 | 0:664899e0b988 | 163 | remove(fname); |
uci1 | 0:664899e0b988 | 164 | } |
uci1 | 0:664899e0b988 | 165 | |
uci1 | 0:664899e0b988 | 166 | SnCommWin::ECommWinResult SnSDUtils::SendAllFiles(SnCommWin* comm, |
uci1 | 3:24c5f0f50bf1 | 167 | const bool doDelete, |
uci1 | 3:24c5f0f50bf1 | 168 | const uint32_t timeout, |
uci1 | 3:24c5f0f50bf1 | 169 | char* const buf, |
uci1 | 6:6f002d202f59 | 170 | const uint32_t bsize, |
uci1 | 6:6f002d202f59 | 171 | const SnConfigFrame& curConf, |
uci1 | 8:95a325df1f6b | 172 | SnEventFrame& evt, |
uci1 | 8:95a325df1f6b | 173 | SnPowerFrame& pow) { |
uci1 | 0:664899e0b988 | 174 | |
uci1 | 0:664899e0b988 | 175 | DIR* d; |
uci1 | 0:664899e0b988 | 176 | struct dirent* dent; |
uci1 | 0:664899e0b988 | 177 | |
uci1 | 0:664899e0b988 | 178 | SnCommWin::ECommWinResult rs = SnCommWin::kUndefFail; |
uci1 | 0:664899e0b988 | 179 | |
uci1 | 0:664899e0b988 | 180 | if ( (d = opendir( kSDsubDir ))!=NULL ) { |
uci1 | 0:664899e0b988 | 181 | FILE* f; |
uci1 | 0:664899e0b988 | 182 | while ( (dent = readdir(d))!=NULL ) { |
uci1 | 0:664899e0b988 | 183 | if (strncmp(dent->d_name, "SnEvts", 6)==0) { |
uci1 | 1:e392595b4b76 | 184 | const bool isCurFile = |
uci1 | 1:e392595b4b76 | 185 | (strcmp(dent->d_name, GetCurFileName())==0); |
uci1 | 1:e392595b4b76 | 186 | if (isCurFile) { |
uci1 | 3:24c5f0f50bf1 | 187 | // file must already be written out! |
uci1 | 1:e392595b4b76 | 188 | f = GetCurFile(); |
uci1 | 1:e392595b4b76 | 189 | } else { |
uci1 | 3:24c5f0f50bf1 | 190 | f = OpenExistingFile(dent->d_name, false); |
uci1 | 1:e392595b4b76 | 191 | } |
uci1 | 6:6f002d202f59 | 192 | rs = comm->SendData(f, dent->d_name, |
uci1 | 8:95a325df1f6b | 193 | curConf, evt, pow, buf, bsize, |
uci1 | 6:6f002d202f59 | 194 | 0, timeout, 0); |
uci1 | 3:24c5f0f50bf1 | 195 | if (isCurFile) { |
uci1 | 3:24c5f0f50bf1 | 196 | // move (back) to the end of the file |
uci1 | 3:24c5f0f50bf1 | 197 | // altho hopefully no writing will happen after this |
uci1 | 3:24c5f0f50bf1 | 198 | fseek(fgCurFile, 0, SEEK_END); |
uci1 | 0:664899e0b988 | 199 | } |
uci1 | 0:664899e0b988 | 200 | } |
uci1 | 0:664899e0b988 | 201 | } |
uci1 | 0:664899e0b988 | 202 | closedir(d); |
uci1 | 0:664899e0b988 | 203 | } |
uci1 | 0:664899e0b988 | 204 | |
uci1 | 0:664899e0b988 | 205 | return rs; |
uci1 | 0:664899e0b988 | 206 | } |
uci1 | 0:664899e0b988 | 207 |