PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
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.

init_t3.cpp 6.7KB

3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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. uint8_t SDClass::fat_type;
  30. uint32_t SDClass::fat1_begin_lba;
  31. uint32_t SDClass::fat2_begin_lba;
  32. uint32_t SDClass::data_begin_lba;
  33. uint32_t SDClass::max_cluster;
  34. uint8_t SDClass::sector2cluster;
  35. File SDClass::rootDir;
  36. static uint32_t unaligned_read32_align16(const void *p)
  37. {
  38. #ifdef KINETISK
  39. return *(const uint32_t *)p;
  40. #else
  41. return *(const uint16_t *)p | (*(const uint16_t *)(p+1) << 16);
  42. #endif
  43. }
  44. static uint32_t unaligned_read16_align8(const void *p)
  45. {
  46. #ifdef KINETISK
  47. return *(const uint16_t *)p;
  48. #else
  49. return *(const uint8_t *)p | (*(const uint8_t *)(p+1) << 8);
  50. #endif
  51. }
  52. #define BPB_BytsPerSec 11 // 2 bytes
  53. #define BPB_SecPerClus 13 // 1 byte
  54. #define BPB_NumFATs 16 // 1 byte
  55. #define BPB_RootEntCnt 17 // 1 byte
  56. #define BPB_TotSec16 19 // 2 bytes
  57. #define BPB_FATSz16 22 // 2 bytes
  58. #define BPB_TotSec32 32 // 4 bytes
  59. #define BPB_FATSz32 36 // 4 bytes
  60. #define BPB_RootClus 44 // 4 bytes
  61. bool SDClass::begin(uint8_t csPin)
  62. {
  63. uint8_t status;
  64. uint32_t cond, hcs, ocr;
  65. // set up the SPI hardware
  66. csreg = PIN_TO_BASEREG(csPin);
  67. csmask = PIN_TO_BITMASK(csPin);
  68. pinMode(csPin, OUTPUT);
  69. DIRECT_WRITE_HIGH(csreg, csmask);
  70. SPI.begin();
  71. // send clocks to initialize hardware
  72. SPI.beginTransaction(SD_SPI_SPEED);
  73. for (uint8_t i=0; i < 5; i++) SPI.transfer16(0xFFFF);
  74. // put the card into idle state
  75. elapsedMillis msec = 0;
  76. while (1) {
  77. status = sd_cmd0();
  78. //Serial.print("cmd0=");
  79. //Serial.println(status);
  80. if (status == 1) break;
  81. SPI.endTransaction();
  82. if (msec > 250) return false;
  83. SPI.beginTransaction(SD_SPI_SPEED);
  84. }
  85. // detect version 1 vs 2 cards
  86. cond = sd_cmd8();
  87. if (cond == 0x80000000) {
  88. // version 1 card
  89. card_type = 1;
  90. hcs = 0;
  91. } else if (cond == 0x1AA) {
  92. // version 2 card
  93. card_type = 2;
  94. hcs = (1<<30);
  95. } else {
  96. SPI.endTransaction();
  97. return false;
  98. }
  99. //Serial.println();
  100. // wait for the card to be ready
  101. msec = 0;
  102. while (1) {
  103. status = sd_acmd41(hcs);
  104. //Serial.println();
  105. if (status == 0) break;
  106. SPI.endTransaction();
  107. if (status > 1) return false;
  108. if (msec > 1500) return false;
  109. SPI.beginTransaction(SD_SPI_SPEED);
  110. }
  111. //Serial.println("card is ready");
  112. // detect high capacity cards
  113. if (card_type == 2) {
  114. ocr = sd_cmd58();
  115. //Serial.print("ocr =");
  116. //Serial.println(ocr, HEX);
  117. if ((ocr >> 30) == 3) card_type = 3;
  118. }
  119. SPI.endTransaction();
  120. //Serial.println("init ok");
  121. // read the MBR (partition table)
  122. SDCache s;
  123. sector_t * mbr = s.read(0);
  124. //Serial.printf(" mbr sig = %04X\n", mbr->u16[255]);
  125. if (mbr->u16[255] != 0xAA55) return false;
  126. uint32_t partition_lba = 0;
  127. uint32_t index = 446;
  128. do {
  129. uint8_t type = mbr->u8[index+4];
  130. //Serial.printf(" partition %d is type %d\n", (index-446)/16+1, type);
  131. if (type == 6 || type == 11 || type == 12) {
  132. partition_lba = unaligned_read32_align16(mbr->u8 + index + 8);
  133. //Serial.printf(" partition lba = %d\n", partition_lba);
  134. break;
  135. }
  136. index += 16;
  137. } while (index < 64);
  138. s.release();
  139. // read the FAT volume ID
  140. sector_t *vol = s.read(partition_lba);
  141. if (vol->u16[255] != 0xAA55) return false;
  142. // BPB_BytsPerSec must be 512 bytes per sector
  143. if (unaligned_read16_align8(vol->u8 + BPB_BytsPerSec) != 512) return false;
  144. // BPB_NumFATs must be 2 copies of the file allocation table
  145. if (vol->u8[BPB_NumFATs] != 2) return false;
  146. uint32_t reserved_sectors = vol->u16[14/2];
  147. if (reserved_sectors == 0) return false;
  148. //Serial.printf(" reserved_sectors = %d\n", reserved_sectors);
  149. uint32_t sectors_per_cluster = vol->u8[BPB_SecPerClus];
  150. //Serial.printf(" sectors_per_cluster = %d\n", sectors_per_cluster);
  151. uint32_t s2c = 31 - __builtin_clz(sectors_per_cluster);
  152. //Serial.printf(" s2c = %d\n", s2c);
  153. sector2cluster = s2c;
  154. uint32_t sectors_per_fat = vol->u16[BPB_FATSz16/2];
  155. if (sectors_per_fat == 0) sectors_per_fat = vol->u32[BPB_FATSz32/4];
  156. //Serial.printf(" sectors_per_fat = %d\n", sectors_per_fat);
  157. uint32_t root_dir_entries = unaligned_read16_align8(vol->u8 + BPB_RootEntCnt);
  158. //Serial.printf(" root_dir_entries = %d\n", root_dir_entries);
  159. uint32_t root_dir_sectors = (root_dir_entries + 15) >> 4;
  160. //Serial.printf(" root_dir_sectors = %d\n", root_dir_sectors);
  161. uint32_t total_sectors = unaligned_read16_align8(vol->u8 + BPB_TotSec16);
  162. if (total_sectors == 0) total_sectors = vol->u32[BPB_TotSec32/4];
  163. //Serial.printf(" total_sectors = %d\n", total_sectors);
  164. fat1_begin_lba = partition_lba + reserved_sectors;
  165. fat2_begin_lba = fat1_begin_lba + sectors_per_fat;
  166. data_begin_lba = fat2_begin_lba + sectors_per_fat + root_dir_sectors;
  167. uint32_t cluster_count = (total_sectors - reserved_sectors
  168. - root_dir_sectors - (sectors_per_fat << 1)) >> s2c;
  169. //Serial.printf(" cluster_count = %d\n", cluster_count);
  170. max_cluster = cluster_count + 1;
  171. if (cluster_count < 4085) {
  172. return false; // FAT12
  173. } else if (cluster_count < 65525) {
  174. fat_type = 16;
  175. rootDir.length = root_dir_entries << 5;
  176. rootDir.start_cluster = partition_lba + reserved_sectors + sectors_per_fat * 2;
  177. rootDir.type = FILE_DIR_ROOT16;
  178. } else {
  179. fat_type = 32;
  180. rootDir.length = 0;
  181. rootDir.start_cluster = vol->u32[BPB_RootClus/4];
  182. //Serial.printf(" root cluster = %d\n", rootDir.start_cluster);
  183. rootDir.type = FILE_DIR;
  184. }
  185. rootDir.current_cluster = rootDir.start_cluster;
  186. rootDir.offset = 0;
  187. s.release();
  188. //Serial.println(sizeof(fatdir_t));
  189. return true;
  190. }
  191. #endif
  192. #endif