ArchiveStorage.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. #include "ArchiveStorage.h"
  2. #include <MeshCore.h>
  3. #ifndef ARCHIVE_DEBUG
  4. #if defined(MQTT_DEBUG) && MQTT_DEBUG
  5. #define ARCHIVE_DEBUG 1
  6. #else
  7. #define ARCHIVE_DEBUG 0
  8. #endif
  9. #endif
  10. #if ARCHIVE_DEBUG
  11. #define ARCHIVE_LOG(fmt, ...) Serial.printf("[ARCHIVE] " fmt "\n", ##__VA_ARGS__)
  12. #else
  13. #define ARCHIVE_LOG(...) do { } while (0)
  14. #endif
  15. namespace {
  16. #if defined(ESP32)
  17. const char* cardTypeName(uint8_t type) {
  18. switch (type) {
  19. case CARD_MMC:
  20. return "mmc";
  21. case CARD_SD:
  22. return "sdsc";
  23. case CARD_SDHC:
  24. return "sdhc";
  25. default:
  26. return "unknown";
  27. }
  28. }
  29. #endif
  30. } // namespace
  31. #if defined(ESP32)
  32. SPIClass* getBoardSharedArchiveSPI() __attribute__((weak));
  33. #endif
  34. ArchiveStorage::ArchiveStorage()
  35. : _attempted(false), _mounted(false), _mount_failed(false), _supported(false), _card_type(0), _spi_bus(HSPI),
  36. _cs_pin(0xFF), _sck_pin(0xFF),
  37. _miso_pin(0xFF), _mosi_pin(0xFF), _card_size_bytes(0), _total_bytes(0), _used_bytes(0)
  38. #if defined(ESP32)
  39. , _spi(nullptr), _owns_spi(false)
  40. #endif
  41. {
  42. }
  43. namespace {
  44. bool mountArchiveSd(SPIClass* spi,
  45. uint8_t spi_bus,
  46. uint8_t cs_pin,
  47. uint8_t sck_pin,
  48. uint8_t miso_pin,
  49. uint8_t mosi_pin) {
  50. if (spi == nullptr) {
  51. return false;
  52. }
  53. #if defined(P_BOARD_IMU_CS)
  54. pinMode(P_BOARD_IMU_CS, OUTPUT);
  55. digitalWrite(P_BOARD_IMU_CS, HIGH);
  56. #endif
  57. pinMode(cs_pin, OUTPUT);
  58. digitalWrite(cs_pin, HIGH);
  59. spi->begin(sck_pin, miso_pin, mosi_pin, cs_pin);
  60. return SD.begin(cs_pin, *spi, 10000000U);
  61. }
  62. } // namespace
  63. void ArchiveStorage::begin() {
  64. if (_attempted) {
  65. return;
  66. }
  67. _attempted = true;
  68. #if defined(ESP32)
  69. _supported = resolvePins();
  70. if (!_supported) {
  71. ARCHIVE_LOG("unsupported: no SD pin mapping");
  72. return;
  73. }
  74. ARCHIVE_LOG("init bus=%u cs=%u sck=%u miso=%u mosi=%u",
  75. static_cast<unsigned>(_spi_bus),
  76. static_cast<unsigned>(_cs_pin),
  77. static_cast<unsigned>(_sck_pin),
  78. static_cast<unsigned>(_miso_pin),
  79. static_cast<unsigned>(_mosi_pin));
  80. _spi = getBoardSharedArchiveSPI();
  81. _owns_spi = (_spi == nullptr);
  82. if (_spi == nullptr) {
  83. _spi = new SPIClass(_spi_bus);
  84. if (_spi == nullptr) {
  85. _mount_failed = true;
  86. ARCHIVE_LOG("mount failed: SPI alloc failed");
  87. return;
  88. }
  89. }
  90. if (!mountArchiveSd(_spi, _spi_bus, _cs_pin, _sck_pin, _miso_pin, _mosi_pin)) {
  91. _mount_failed = true;
  92. ARCHIVE_LOG("mount failed bus=%u cs=%u sck=%u miso=%u mosi=%u",
  93. static_cast<unsigned>(_spi_bus),
  94. static_cast<unsigned>(_cs_pin),
  95. static_cast<unsigned>(_sck_pin),
  96. static_cast<unsigned>(_miso_pin),
  97. static_cast<unsigned>(_mosi_pin));
  98. return;
  99. }
  100. _mounted = true;
  101. if (!SD.exists(getFsStatsPath())) {
  102. SD.mkdir(getFsStatsPath());
  103. }
  104. refreshCardInfo();
  105. ARCHIVE_LOG("mounted type=%s card=%llu total=%llu used=%llu path=%s",
  106. getCardTypeName(),
  107. static_cast<unsigned long long>(_card_size_bytes),
  108. static_cast<unsigned long long>(_total_bytes),
  109. static_cast<unsigned long long>(_used_bytes),
  110. getLogicalStatsPath());
  111. #else
  112. _supported = false;
  113. #endif
  114. }
  115. bool ArchiveStorage::recover() {
  116. #if defined(ESP32)
  117. if (!_supported || _spi == nullptr) {
  118. return false;
  119. }
  120. ARCHIVE_LOG("recover begin bus=%u cs=%u", static_cast<unsigned>(_spi_bus), static_cast<unsigned>(_cs_pin));
  121. SD.end();
  122. if (_owns_spi) {
  123. _spi->end();
  124. }
  125. _mounted = false;
  126. _mount_failed = false;
  127. _card_size_bytes = 0;
  128. _total_bytes = 0;
  129. _used_bytes = 0;
  130. if (!mountArchiveSd(_spi, _spi_bus, _cs_pin, _sck_pin, _miso_pin, _mosi_pin)) {
  131. _mount_failed = true;
  132. ARCHIVE_LOG("recover failed bus=%u cs=%u", static_cast<unsigned>(_spi_bus), static_cast<unsigned>(_cs_pin));
  133. return false;
  134. }
  135. _mounted = true;
  136. if (!SD.exists(getFsStatsPath())) {
  137. SD.mkdir(getFsStatsPath());
  138. }
  139. refreshCardInfo();
  140. ARCHIVE_LOG("recover mounted type=%s card=%llu total=%llu used=%llu path=%s",
  141. getCardTypeName(),
  142. static_cast<unsigned long long>(_card_size_bytes),
  143. static_cast<unsigned long long>(_total_bytes),
  144. static_cast<unsigned long long>(_used_bytes),
  145. getLogicalStatsPath());
  146. return true;
  147. #else
  148. return false;
  149. #endif
  150. }
  151. bool ArchiveStorage::isSupported() const {
  152. return _supported;
  153. }
  154. FILESYSTEM* ArchiveStorage::getFS() {
  155. #if defined(ESP32)
  156. return _mounted ? &SD : nullptr;
  157. #else
  158. return nullptr;
  159. #endif
  160. }
  161. const char* ArchiveStorage::getCardTypeName() const {
  162. #if defined(ESP32)
  163. if (!_mounted) {
  164. return "unavailable";
  165. }
  166. return cardTypeName(_card_type);
  167. #else
  168. return "unsupported";
  169. #endif
  170. }
  171. #if defined(ESP32)
  172. bool ArchiveStorage::resolvePins() {
  173. #if defined(P_BOARD_SPI_SCK) && defined(P_BOARD_SPI_MISO) && defined(P_BOARD_SPI_MOSI) && defined(P_BOARD_SPI_CS)
  174. _sck_pin = static_cast<uint8_t>(P_BOARD_SPI_SCK);
  175. _miso_pin = static_cast<uint8_t>(P_BOARD_SPI_MISO);
  176. _mosi_pin = static_cast<uint8_t>(P_BOARD_SPI_MOSI);
  177. _cs_pin = static_cast<uint8_t>(P_BOARD_SPI_CS);
  178. #if defined(TBEAM_SUPREME_SX1262) && defined(FSPI)
  179. _spi_bus = FSPI;
  180. #endif
  181. return true;
  182. #elif defined(TBEAM_SUPREME_SX1262)
  183. // T-Beam S3 Supreme SD/IMU shared SPI bus pins.
  184. _sck_pin = 36;
  185. _miso_pin = 37;
  186. _mosi_pin = 35;
  187. _cs_pin = 47;
  188. #if defined(FSPI)
  189. _spi_bus = FSPI;
  190. #endif
  191. return true;
  192. #elif defined(TBEAM_1W)
  193. // T-Beam 1W microSD shares the board SPI pins but uses its own chip select.
  194. _sck_pin = 13;
  195. _miso_pin = 12;
  196. _mosi_pin = 11;
  197. _cs_pin = 10;
  198. #if defined(FSPI)
  199. _spi_bus = FSPI;
  200. #endif
  201. return true;
  202. #elif defined(HAS_SDCARD) && defined(SDCARD_CS)
  203. _cs_pin = static_cast<uint8_t>(SDCARD_CS);
  204. #if defined(SPI_SCK) && defined(SPI_MISO) && defined(SPI_MOSI)
  205. _sck_pin = static_cast<uint8_t>(SPI_SCK);
  206. _miso_pin = static_cast<uint8_t>(SPI_MISO);
  207. _mosi_pin = static_cast<uint8_t>(SPI_MOSI);
  208. return true;
  209. #elif defined(P_LORA_SCLK) && defined(P_LORA_MISO) && defined(P_LORA_MOSI)
  210. _sck_pin = static_cast<uint8_t>(P_LORA_SCLK);
  211. _miso_pin = static_cast<uint8_t>(P_LORA_MISO);
  212. _mosi_pin = static_cast<uint8_t>(P_LORA_MOSI);
  213. return true;
  214. #endif
  215. #endif
  216. return false;
  217. }
  218. void ArchiveStorage::refreshCardInfo() {
  219. if (!_mounted) {
  220. _card_type = 0;
  221. _card_size_bytes = 0;
  222. _total_bytes = 0;
  223. _used_bytes = 0;
  224. return;
  225. }
  226. if (_card_type == 0) {
  227. _card_type = SD.cardType();
  228. }
  229. _card_size_bytes = SD.cardSize();
  230. _total_bytes = SD.totalBytes();
  231. _used_bytes = SD.usedBytes();
  232. if (_total_bytes == 0) {
  233. _total_bytes = _card_size_bytes;
  234. }
  235. }
  236. #endif