PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

296 linhas
9.6KB

  1. /* Arduino SdFat Library
  2. * Copyright (C) 2009 by William Greiman
  3. *
  4. * This file is part of the Arduino SdFat Library
  5. *
  6. * This Library is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This Library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with the Arduino SdFat Library. If not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20. #include <SdFat.h>
  21. //------------------------------------------------------------------------------
  22. // raw block cache
  23. // init cacheBlockNumber_to invalid SD block number
  24. uint32_t SdVolume::cacheBlockNumber_ = 0XFFFFFFFF;
  25. cache_t SdVolume::cacheBuffer_; // 512 byte cache for Sd2Card
  26. Sd2Card* SdVolume::sdCard_; // pointer to SD card object
  27. uint8_t SdVolume::cacheDirty_ = 0; // cacheFlush() will write block if true
  28. uint32_t SdVolume::cacheMirrorBlock_ = 0; // mirror block for second FAT
  29. //------------------------------------------------------------------------------
  30. // find a contiguous group of clusters
  31. uint8_t SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
  32. // start of group
  33. uint32_t bgnCluster;
  34. // flag to save place to start next search
  35. uint8_t setStart;
  36. // set search start cluster
  37. if (*curCluster) {
  38. // try to make file contiguous
  39. bgnCluster = *curCluster + 1;
  40. // don't save new start location
  41. setStart = false;
  42. } else {
  43. // start at likely place for free cluster
  44. bgnCluster = allocSearchStart_;
  45. // save next search start if one cluster
  46. setStart = 1 == count;
  47. }
  48. // end of group
  49. uint32_t endCluster = bgnCluster;
  50. // last cluster of FAT
  51. uint32_t fatEnd = clusterCount_ + 1;
  52. // search the FAT for free clusters
  53. for (uint32_t n = 0;; n++, endCluster++) {
  54. // can't find space checked all clusters
  55. if (n >= clusterCount_) return false;
  56. // past end - start from beginning of FAT
  57. if (endCluster > fatEnd) {
  58. bgnCluster = endCluster = 2;
  59. }
  60. uint32_t f;
  61. if (!fatGet(endCluster, &f)) return false;
  62. if (f != 0) {
  63. // cluster in use try next cluster as bgnCluster
  64. bgnCluster = endCluster + 1;
  65. } else if ((endCluster - bgnCluster + 1) == count) {
  66. // done - found space
  67. break;
  68. }
  69. }
  70. // mark end of chain
  71. if (!fatPutEOC(endCluster)) return false;
  72. // link clusters
  73. while (endCluster > bgnCluster) {
  74. if (!fatPut(endCluster - 1, endCluster)) return false;
  75. endCluster--;
  76. }
  77. if (*curCluster != 0) {
  78. // connect chains
  79. if (!fatPut(*curCluster, bgnCluster)) return false;
  80. }
  81. // return first cluster number to caller
  82. *curCluster = bgnCluster;
  83. // remember possible next free cluster
  84. if (setStart) allocSearchStart_ = bgnCluster + 1;
  85. return true;
  86. }
  87. //------------------------------------------------------------------------------
  88. uint8_t SdVolume::cacheFlush(void) {
  89. if (cacheDirty_) {
  90. if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data)) {
  91. return false;
  92. }
  93. // mirror FAT tables
  94. if (cacheMirrorBlock_) {
  95. if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data)) {
  96. return false;
  97. }
  98. cacheMirrorBlock_ = 0;
  99. }
  100. cacheDirty_ = 0;
  101. }
  102. return true;
  103. }
  104. //------------------------------------------------------------------------------
  105. uint8_t SdVolume::cacheRawBlock(uint32_t blockNumber, uint8_t action) {
  106. if (cacheBlockNumber_ != blockNumber) {
  107. if (!cacheFlush()) return false;
  108. if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) return false;
  109. cacheBlockNumber_ = blockNumber;
  110. }
  111. cacheDirty_ |= action;
  112. return true;
  113. }
  114. //------------------------------------------------------------------------------
  115. // cache a zero block for blockNumber
  116. uint8_t SdVolume::cacheZeroBlock(uint32_t blockNumber) {
  117. if (!cacheFlush()) return false;
  118. // loop take less flash than memset(cacheBuffer_.data, 0, 512);
  119. for (uint16_t i = 0; i < 512; i++) {
  120. cacheBuffer_.data[i] = 0;
  121. }
  122. cacheBlockNumber_ = blockNumber;
  123. cacheSetDirty();
  124. return true;
  125. }
  126. //------------------------------------------------------------------------------
  127. // return the size in bytes of a cluster chain
  128. uint8_t SdVolume::chainSize(uint32_t cluster, uint32_t* size) const {
  129. uint32_t s = 0;
  130. do {
  131. if (!fatGet(cluster, &cluster)) return false;
  132. s += 512UL << clusterSizeShift_;
  133. } while (!isEOC(cluster));
  134. *size = s;
  135. return true;
  136. }
  137. //------------------------------------------------------------------------------
  138. // Fetch a FAT entry
  139. uint8_t SdVolume::fatGet(uint32_t cluster, uint32_t* value) const {
  140. if (cluster > (clusterCount_ + 1)) return false;
  141. uint32_t lba = fatStartBlock_;
  142. lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7;
  143. if (lba != cacheBlockNumber_) {
  144. if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false;
  145. }
  146. if (fatType_ == 16) {
  147. *value = cacheBuffer_.fat16[cluster & 0XFF];
  148. } else {
  149. *value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK;
  150. }
  151. return true;
  152. }
  153. //------------------------------------------------------------------------------
  154. // Store a FAT entry
  155. uint8_t SdVolume::fatPut(uint32_t cluster, uint32_t value) {
  156. // error if reserved cluster
  157. if (cluster < 2) return false;
  158. // error if not in FAT
  159. if (cluster > (clusterCount_ + 1)) return false;
  160. // calculate block address for entry
  161. uint32_t lba = fatStartBlock_;
  162. lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7;
  163. if (lba != cacheBlockNumber_) {
  164. if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false;
  165. }
  166. // store entry
  167. if (fatType_ == 16) {
  168. cacheBuffer_.fat16[cluster & 0XFF] = value;
  169. } else {
  170. cacheBuffer_.fat32[cluster & 0X7F] = value;
  171. }
  172. cacheSetDirty();
  173. // mirror second FAT
  174. if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
  175. return true;
  176. }
  177. //------------------------------------------------------------------------------
  178. // free a cluster chain
  179. uint8_t SdVolume::freeChain(uint32_t cluster) {
  180. // clear free cluster location
  181. allocSearchStart_ = 2;
  182. do {
  183. uint32_t next;
  184. if (!fatGet(cluster, &next)) return false;
  185. // free cluster
  186. if (!fatPut(cluster, 0)) return false;
  187. cluster = next;
  188. } while (!isEOC(cluster));
  189. return true;
  190. }
  191. //------------------------------------------------------------------------------
  192. /**
  193. * Initialize a FAT volume.
  194. *
  195. * \param[in] dev The SD card where the volume is located.
  196. *
  197. * \param[in] part The partition to be used. Legal values for \a part are
  198. * 1-4 to use the corresponding partition on a device formatted with
  199. * a MBR, Master Boot Record, or zero if the device is formatted as
  200. * a super floppy with the FAT boot sector in block zero.
  201. *
  202. * \return The value one, true, is returned for success and
  203. * the value zero, false, is returned for failure. Reasons for
  204. * failure include not finding a valid partition, not finding a valid
  205. * FAT file system in the specified partition or an I/O error.
  206. */
  207. uint8_t SdVolume::init(Sd2Card* dev, uint8_t part) {
  208. uint32_t volumeStartBlock = 0;
  209. sdCard_ = dev;
  210. // if part == 0 assume super floppy with FAT boot sector in block zero
  211. // if part > 0 assume mbr volume with partition table
  212. if (part) {
  213. if (part > 4)return false;
  214. if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false;
  215. part_t* p = &cacheBuffer_.mbr.part[part-1];
  216. if ((p->boot & 0X7F) !=0 ||
  217. p->totalSectors < 100 ||
  218. p->firstSector == 0) {
  219. // not a valid partition
  220. return false;
  221. }
  222. volumeStartBlock = p->firstSector;
  223. }
  224. if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false;
  225. bpb_t* bpb = &cacheBuffer_.fbs.bpb;
  226. if (bpb->bytesPerSector != 512 ||
  227. bpb->fatCount == 0 ||
  228. bpb->reservedSectorCount == 0 ||
  229. bpb->sectorsPerCluster == 0) {
  230. // not valid FAT volume
  231. return false;
  232. }
  233. fatCount_ = bpb->fatCount;
  234. blocksPerCluster_ = bpb->sectorsPerCluster;
  235. // determine shift that is same as multiply by blocksPerCluster_
  236. clusterSizeShift_ = 0;
  237. while (blocksPerCluster_ != (1 << clusterSizeShift_)) {
  238. // error if not power of 2
  239. if (clusterSizeShift_++ > 7) return false;
  240. }
  241. blocksPerFat_ = bpb->sectorsPerFat16 ?
  242. bpb->sectorsPerFat16 : bpb->sectorsPerFat32;
  243. fatStartBlock_ = volumeStartBlock + bpb->reservedSectorCount;
  244. // count for FAT16 zero for FAT32
  245. rootDirEntryCount_ = bpb->rootDirEntryCount;
  246. // directory start for FAT16 dataStart for FAT32
  247. rootDirStart_ = fatStartBlock_ + bpb->fatCount * blocksPerFat_;
  248. // data start for FAT16 and FAT32
  249. dataStartBlock_ = rootDirStart_ + ((32 * bpb->rootDirEntryCount + 511)/512);
  250. // total blocks for FAT16 or FAT32
  251. uint32_t totalBlocks = bpb->totalSectors16 ?
  252. bpb->totalSectors16 : bpb->totalSectors32;
  253. // total data blocks
  254. clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock);
  255. // divide by cluster size to get cluster count
  256. clusterCount_ >>= clusterSizeShift_;
  257. // FAT type is determined by cluster count
  258. if (clusterCount_ < 4085) {
  259. fatType_ = 12;
  260. } else if (clusterCount_ < 65525) {
  261. fatType_ = 16;
  262. } else {
  263. rootDirStart_ = bpb->fat32RootCluster;
  264. fatType_ = 32;
  265. }
  266. return true;
  267. }