|
3 | 3 | // SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC
|
4 | 4 | //
|
5 | 5 | // SPDX-License-Identifier: MIT
|
| 6 | + |
| 7 | +#include "shared-module/sdcardio/__init__.h" |
| 8 | + |
| 9 | +#include "extmod/vfs_fat.h" |
| 10 | + |
| 11 | +#include "shared-bindings/busio/SPI.h" |
| 12 | +#include "shared-bindings/digitalio/DigitalInOut.h" |
| 13 | +#include "shared-bindings/sdcardio/SDCard.h" |
| 14 | + |
| 15 | +#include "supervisor/filesystem.h" |
| 16 | + |
| 17 | +#ifdef DEFAULT_SD_CARD_DETECT |
| 18 | +static digitalio_digitalinout_obj_t sd_card_detect_pin; |
| 19 | +static sdcardio_sdcard_obj_t sdcard; |
| 20 | + |
| 21 | +static mp_vfs_mount_t _sdcard_vfs; |
| 22 | +fs_user_mount_t _sdcard_usermount; |
| 23 | + |
| 24 | +static bool _init_error = false; |
| 25 | +static bool _mounted = false; |
| 26 | + |
| 27 | +#ifdef DEFAULT_SD_MOSI |
| 28 | +static busio_spi_obj_t busio_spi_obj; |
| 29 | +#endif |
| 30 | +#endif |
| 31 | + |
| 32 | +void sdcardio_init(void) { |
| 33 | + #ifdef DEFAULT_SD_CARD_DETECT |
| 34 | + sd_card_detect_pin.base.type = &digitalio_digitalinout_type; |
| 35 | + common_hal_digitalio_digitalinout_construct(&sd_card_detect_pin, DEFAULT_SD_CARD_DETECT); |
| 36 | + common_hal_digitalio_digitalinout_switch_to_input(&sd_card_detect_pin, PULL_UP); |
| 37 | + common_hal_digitalio_digitalinout_never_reset(&sd_card_detect_pin); |
| 38 | + #endif |
| 39 | +} |
| 40 | + |
| 41 | +void automount_sd_card(void) { |
| 42 | + #ifdef DEFAULT_SD_CARD_DETECT |
| 43 | + if (common_hal_digitalio_digitalinout_get_value(&sd_card_detect_pin) != DEFAULT_SD_CARD_INSERTED) { |
| 44 | + // No card. |
| 45 | + _init_error = false; |
| 46 | + if (_mounted) { |
| 47 | + // Unmount the card. |
| 48 | + mp_vfs_mount_t *cur = MP_STATE_VM(vfs_mount_table); |
| 49 | + if (cur == &_sdcard_vfs) { |
| 50 | + MP_STATE_VM(vfs_mount_table) = cur->next; |
| 51 | + } else { |
| 52 | + while (cur->next != &_sdcard_vfs && cur != NULL) { |
| 53 | + cur = cur->next; |
| 54 | + } |
| 55 | + if (cur != NULL) { |
| 56 | + cur->next = _sdcard_vfs.next; |
| 57 | + } |
| 58 | + } |
| 59 | + _sdcard_vfs.next = NULL; |
| 60 | + |
| 61 | + #ifdef DEFAULT_SD_MOSI |
| 62 | + common_hal_busio_spi_deinit(&busio_spi_obj); |
| 63 | + #endif |
| 64 | + _mounted = false; |
| 65 | + } |
| 66 | + return; |
| 67 | + } else if (_init_error || _mounted) { |
| 68 | + // We've already tried and failed to init the card. Don't try again. |
| 69 | + return; |
| 70 | + } |
| 71 | + |
| 72 | + busio_spi_obj_t *spi_obj; |
| 73 | + #ifndef DEFAULT_SD_MOSI |
| 74 | + spi_obj = MP_OBJ_TO_PTR(common_hal_board_create_spi(0)); |
| 75 | + #else |
| 76 | + spi_obj = &busio_spi_obj; |
| 77 | + spi_obj->base.type = &busio_spi_type; |
| 78 | + common_hal_busio_spi_construct(spi_obj, DEFAULT_SD_SCK, DEFAULT_SD_MOSI, DEFAULT_SD_MISO, false); |
| 79 | + common_hal_busio_spi_never_reset(spi_obj); |
| 80 | + #endif |
| 81 | + sdcard.base.type = &sdcardio_SDCard_type; |
| 82 | + mp_rom_error_text_t error = sdcardio_sdcard_construct(&sdcard, spi_obj, DEFAULT_SD_CS, 25000000); |
| 83 | + if (error != NULL) { |
| 84 | + // Failed to communicate with the card. |
| 85 | + _init_error = true; |
| 86 | + } |
| 87 | + common_hal_digitalio_digitalinout_never_reset(&sdcard.cs); |
| 88 | + |
| 89 | + fs_user_mount_t *vfs = &_sdcard_usermount; |
| 90 | + vfs->base.type = &mp_fat_vfs_type; |
| 91 | + vfs->fatfs.drv = vfs; |
| 92 | + |
| 93 | + // Initialise underlying block device |
| 94 | + vfs->blockdev.block_size = FF_MIN_SS; // default, will be populated by call to MP_BLOCKDEV_IOCTL_BLOCK_SIZE |
| 95 | + mp_vfs_blockdev_init(&vfs->blockdev, &sdcard); |
| 96 | + |
| 97 | + // mount the block device so the VFS methods can be used |
| 98 | + FRESULT res = f_mount(&vfs->fatfs); |
| 99 | + if (res != FR_OK) { |
| 100 | + _mounted = false; |
| 101 | + _init_error = true; |
| 102 | + common_hal_sdcardio_sdcard_deinit(&sdcard); |
| 103 | + #ifdef DEFAULT_SD_MOSI |
| 104 | + common_hal_busio_spi_deinit(spi_obj); |
| 105 | + #endif |
| 106 | + return; |
| 107 | + } |
| 108 | + |
| 109 | + filesystem_set_concurrent_write_protection(vfs, true); |
| 110 | + filesystem_set_writable_by_usb(vfs, false); |
| 111 | + |
| 112 | + mp_vfs_mount_t *sdcard_vfs = &_sdcard_vfs; |
| 113 | + sdcard_vfs->str = "/sd"; |
| 114 | + sdcard_vfs->len = 3; |
| 115 | + sdcard_vfs->obj = MP_OBJ_FROM_PTR(&_sdcard_usermount); |
| 116 | + sdcard_vfs->next = MP_STATE_VM(vfs_mount_table); |
| 117 | + MP_STATE_VM(vfs_mount_table) = sdcard_vfs; |
| 118 | + _mounted = true; |
| 119 | + #endif |
| 120 | +} |
0 commit comments