Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

10 лет назад
10 лет назад
9 лет назад
10 лет назад
9 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /* Optimized SD Library for Teensy 3.X
  2. * Copyright (c) 2015, Paul Stoffregen, paul@pjrc.com
  3. *
  4. * Development of this SD library was funded by PJRC.COM, LLC by sales of
  5. * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop
  6. * open source software by purchasing genuine Teensy or other PJRC products.
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice, development funding notice, and this permission
  16. * notice shall be included in all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #if defined(__arm__)
  27. #include "SD_t3.h"
  28. #ifdef USE_TEENSY3_OPTIMIZED_CODE
  29. #define cache_t SDCache::cache_t
  30. #define sector_t SDClass::sector_t
  31. cache_t *SDCache::cache_list = NULL;
  32. cache_t SDCache::cache[SD_CACHE_SIZE];
  33. #define CACHE_FLAG_HAS_DATA 1
  34. #define CACHE_FLAG_IS_DIRTY 2
  35. #define CACHE_FLAG_IS_FAT 4
  36. //#define PRINT_SECTORS
  37. #ifdef PRINT_SECTORS
  38. static void print_sector(const void *data)
  39. {
  40. const uint8_t *p = (const uint8_t *)data;
  41. for (int i=0; i < 512; i++) {
  42. Serial.printf(" %02X", *p++);
  43. if ((i & 31) == 31) Serial.println();
  44. }
  45. }
  46. #endif
  47. void SDCache::print_cache(void)
  48. {
  49. #if 0
  50. const cache_t *end=cache+SD_CACHE_SIZE;
  51. for (cache_t *c = cache; c < end; c++) {
  52. Serial.printf(" cache index %u, lba= %u, ucount=%u, flags=%u\n",
  53. c - cache, c->lba, c->usagecount, c->flags);
  54. }
  55. Serial.print(" cache order:");
  56. for (cache_t *c = cache_list; c; c = c->next) {
  57. Serial.printf(" %u ->", c - cache);
  58. }
  59. Serial.println();
  60. #endif
  61. }
  62. // Read a sector into the cache. If the sector is already cached,
  63. // of course no actual read occurs. This is the primary function
  64. // used to access the SD card.
  65. //
  66. sector_t * SDCache::read(uint32_t lba, bool is_fat)
  67. {
  68. sector_t *ret = NULL;
  69. //uint32_t slot=0, ucount=0;
  70. // the entire read operation, including all cache manipulation,
  71. // needs to be protected with exclusive access to the hardware.
  72. //Serial.printf("cache read: lba = %d\n", lba);
  73. SPI.beginTransaction(SD_SPI_SPEED);
  74. // does the cache already have the sector?
  75. cache_t *c = get(lba);
  76. if (c) {
  77. if (c->flags & CACHE_FLAG_HAS_DATA) {
  78. //Serial.printf(" cache hit, lba=%u\n", lba);
  79. ret = &c->data;
  80. } else {
  81. if (SDClass::sd_read(lba, &c->data)) {
  82. c->flags = CACHE_FLAG_HAS_DATA;
  83. if (is_fat) c->flags |= CACHE_FLAG_IS_FAT;
  84. ret = &c->data;
  85. //Serial.printf(" cache miss, lba=%u\n", lba);
  86. } else {
  87. //Serial.printf(" cache miss: read error, lba=%u\n", lba);
  88. }
  89. }
  90. } else {
  91. //Serial.printf(" cache full & all in use\n", lba);
  92. }
  93. SPI.endTransaction();
  94. //print_cache();
  95. return ret;
  96. }
  97. // Read a whole 512 byte sector directly to memory. If the sector is
  98. // already cached, of course no actual read occurs and data is copied
  99. // from the cache. When the sector is not cached, it's transferred
  100. // directly from SD card to memory, bypassing the cache.
  101. //
  102. bool SDCache::read(uint32_t lba, void *buffer)
  103. {
  104. bool ret = true;
  105. SPI.beginTransaction(SD_SPI_SPEED);
  106. cache_t *c = get(lba, false);
  107. if (!c || !(c->flags & CACHE_FLAG_HAS_DATA)) {
  108. ret = SDClass::sd_read(lba, buffer);
  109. }
  110. SPI.endTransaction();
  111. if (c) {
  112. if ((c->flags & CACHE_FLAG_HAS_DATA)) {
  113. memcpy(buffer, &c->data, 512);
  114. release();
  115. return true;
  116. }
  117. release();
  118. }
  119. return ret;
  120. }
  121. // locate a sector in the cache.
  122. cache_t * SDCache::get(uint32_t lba, bool allocate)
  123. {
  124. cache_t *c, *p=NULL, *last=NULL, *plast=NULL;
  125. // TODO: move initialization to a function called when the SD card is initialized
  126. if (cache_list == NULL) init();
  127. // have we already acquired a cache entry?
  128. if (item) {
  129. // if it's the desired block, use it
  130. if (item->lba == lba) return item;
  131. // if not, release our hold on it
  132. release();
  133. }
  134. __disable_irq();
  135. c = cache_list;
  136. do {
  137. if (c->lba == lba) {
  138. if (p) {
  139. p->next = c->next;
  140. c->next = cache_list;
  141. cache_list = c;
  142. }
  143. c->usagecount++;
  144. __enable_irq();
  145. item = c;
  146. return item;
  147. }
  148. if (c->usagecount == 0) {
  149. plast = p;
  150. last = c;
  151. }
  152. p = c;
  153. c = c->next;
  154. } while (c);
  155. if (allocate && last) {
  156. if (plast) {
  157. plast->next = last->next;
  158. last->next = cache_list;
  159. cache_list = last;
  160. }
  161. last->usagecount = 1;
  162. // TODO: flush if dirty
  163. last->lba = lba;
  164. last->flags = 0;
  165. item = last;
  166. }
  167. __enable_irq();
  168. return item;
  169. }
  170. void SDCache::init(void)
  171. {
  172. cache_t *c = cache;
  173. cache_t *end = c + SD_CACHE_SIZE;
  174. //Serial.println("cache init");
  175. __disable_irq();
  176. do {
  177. c->lba = 0xFFFFFFFF;
  178. c->usagecount = 0;
  179. c->flags = 0;
  180. c->next = c + 1;
  181. c = c + 1;
  182. } while (c < end);
  183. c--;
  184. c->next = NULL;
  185. cache_list = cache;
  186. __enable_irq();
  187. }
  188. void SDCache::dirty(void)
  189. {
  190. __disable_irq();
  191. item->flags |= CACHE_FLAG_IS_DIRTY;
  192. __enable_irq();
  193. }
  194. void SDCache::release(void)
  195. {
  196. //Serial.printf("cache release\n");
  197. if (item) {
  198. __disable_irq();
  199. item->usagecount--;
  200. //uint32_t ucount = item->usagecount;
  201. //uint32_t lba = item->lba;
  202. //Serial.printf("release %d, %d, slot %u\n", item->lba, item->usagecount, item-cache);
  203. __enable_irq();
  204. item = NULL;
  205. }
  206. }
  207. #endif
  208. #endif