You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
5.6KB

  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[SD_CACHE_SIZE];
  32. #define CACHE_FLAG_HAS_DATA 1
  33. #define CACHE_FLAG_IS_DIRTY 2
  34. #define CACHE_FLAG_IS_FAT 4
  35. /*
  36. static void print_sector(const void *data)
  37. {
  38. const uint8_t *p = (const uint8_t *)data;
  39. for (int i=0; i < 512; i++) {
  40. Serial.printf(" %02X", *p++);
  41. if ((i & 31) == 31) Serial.println();
  42. }
  43. }
  44. */
  45. // Read a sector into the cache. If the sector is already cached,
  46. // of course no actual read occurs. This is the primary function
  47. // used to access the SD card.
  48. //
  49. sector_t * SDCache::read(uint32_t lba, bool is_fat)
  50. {
  51. sector_t *ret = NULL;
  52. //uint32_t slot=0, ucount=0;
  53. // the entire read operation, including all cache manipulation,
  54. // needs to be protected with exclusive access to the hardware.
  55. //Serial.printf("cache read: lba = %d\n", lba);
  56. SPI.beginTransaction(SD_SPI_SPEED);
  57. // does the cache already have the sector?
  58. cache_t *c = find(lba);
  59. if (c) {
  60. ret = &c->data;
  61. } else {
  62. c = empty();
  63. if (c != NULL) {
  64. // TODO: if dirty, write to SD card
  65. if (SDClass::sd_read(lba, &c->data)) {
  66. item = c;
  67. c->lba = lba;
  68. c->usagecount = 1;
  69. c->flags = CACHE_FLAG_HAS_DATA;
  70. if (is_fat) c->flags |= CACHE_FLAG_IS_FAT;
  71. ret = &c->data;
  72. //Serial.printf("cache read %u\n", lba);
  73. //print_sector(&c->data);
  74. }
  75. }
  76. }
  77. //if (c) slot = c - cache, ucount = c->usagecount;
  78. SPI.endTransaction();
  79. //if (ret) {
  80. //Serial.printf("read %u, %u, slot %u\n", lba, ucount, slot);
  81. //} else {
  82. //Serial.printf("read %u, FAIL\n", lba);
  83. //}
  84. return ret;
  85. }
  86. // Read a whole 512 byte sector directly to memory. If the sector is
  87. // already cached, of course no actual read occurs and data is copied
  88. // from the cache. When the sector is not cached, it's transferred
  89. // directly from SD card to memory, bypassing the cache.
  90. //
  91. bool SDCache::read(uint32_t lba, void *buffer)
  92. {
  93. bool ret = true;
  94. SPI.beginTransaction(SD_SPI_SPEED);
  95. cache_t *c = find(lba);
  96. if (!c) ret = SDClass::sd_read(lba, buffer);
  97. SPI.endTransaction();
  98. if (c) memcpy(buffer, &c->data, 512);
  99. return ret;
  100. }
  101. sector_t * SDCache::alloc(uint32_t lba)
  102. {
  103. return NULL;
  104. }
  105. void SDCache::priority(signed int n)
  106. {
  107. if (!item) return;
  108. if (n > 0) {
  109. __disable_irq();
  110. signed int pri = (int)(item->priority) + n;
  111. if (pri > 255) pri = 255;
  112. item->priority = pri;
  113. __enable_irq();
  114. } else {
  115. __disable_irq();
  116. signed int pri = (int)(item->priority) + n;
  117. if (pri < 0) pri = 0;
  118. item->priority = pri;
  119. __enable_irq();
  120. }
  121. }
  122. void SDCache::priority(uint32_t lba, signed int n)
  123. {
  124. // TODO: if any a specific sector is cached, adjust its priority
  125. }
  126. void SDCache::dirty(void)
  127. {
  128. __disable_irq();
  129. item->usagecount |= CACHE_FLAG_IS_DIRTY;
  130. __enable_irq();
  131. }
  132. void SDCache::release(void)
  133. {
  134. //Serial.printf("cache release\n");
  135. if (item) {
  136. __disable_irq();
  137. item->usagecount--;
  138. //uint32_t ucount = item->usagecount;
  139. //uint32_t lba = item->lba;
  140. //Serial.printf("release %d, %d, slot %u\n", item->lba, item->usagecount, item-cache);
  141. __enable_irq();
  142. item = NULL;
  143. }
  144. }
  145. cache_t * SDCache::find(uint32_t lba)
  146. {
  147. //Serial.printf("SDCache::find, lba=%n\n", lba);
  148. // have we already acquired a cache entry?
  149. if (item) {
  150. //Serial.printf(" item exists, lba=%d\n", item->lba);
  151. // if it's the desired block, use it
  152. if (item->lba == lba) return item;
  153. // if not, release our hold on it
  154. //Serial.printf("cache find release\n");
  155. item->usagecount--;
  156. item = NULL;
  157. }
  158. // does the cache already have the sector we want?
  159. const cache_t *end=cache+SD_CACHE_SIZE;
  160. for (cache_t *c = cache; c < end; c++) {
  161. if ((c->flags) && (c->lba == lba)) {
  162. //Serial.printf(" item found\n");
  163. item = c;
  164. c->usagecount++;
  165. return c;
  166. }
  167. }
  168. //Serial.printf(" item not found\n");
  169. // the desired sector isn't in the cache
  170. return NULL;
  171. }
  172. cache_t * SDCache::empty(void)
  173. {
  174. const cache_t *end=cache+SD_CACHE_SIZE;
  175. cache_t *useme = NULL;
  176. uint32_t lowest_priority = 0xFF;
  177. for (cache_t *c = cache; c < end; c++) {
  178. if (c->usagecount == 0 && c->priority < lowest_priority) {
  179. useme = c;
  180. lowest_priority = c->priority;
  181. if (lowest_priority == 0) break;
  182. }
  183. }
  184. return useme;
  185. }
  186. #endif
  187. #endif