ESP32: raw SD IO#2343
Conversation
Move the "sdmmc" / "sdspi" host and slot configuration out of nif_esp_mount into sdcard_config_from_source so the upcoming raw block device NIFs can reuse it instead of duplicating the option parsing. Pure refactor: the FAT mount path is unchanged. Signed-off-by: Davide Bettio <davide@uninstall.it>
Add esp:sdcard_open/2, esp:sdcard_read/2, esp:sdcard_write/3, esp:sdcard_info/1 and esp:sdcard_close/1 to read and write raw SD card sectors without mounting a filesystem, for custom filesystems, partition inspection and raw imaging. The card is opened with the same source and options as esp:mount/4 but initialized via sdmmc_card_init with no VFS/FAT layer. A new AVM_ENABLE_RAW_SDCARD_NIFS option enables them independently of the mount NIFs, so a raw-only build links no filesystem code. Signed-off-by: Davide Bettio <davide@uninstall.it>
PR Review — ESP32 raw SD card block device NIFsReviewed commits:
Files: Verdict: changes requested. One blocker (data corruption on large cards in the IDF≥6 path), Summary table
Confirmed clean: the 1. 🔴 Blocker — IDF≥6 blockdev path truncates the sector byte address to 32 bits
return dev->blockdev->ops->read(dev->blockdev, dst, dev->sector_size,
(uint64_t) sector * dev->sector_size, dev->sector_size);The address math is correct here, but inside ESP-IDF v6 size_t start_sector_num = (size_t) addr / sector_size;
size_t last_byte_addr = (size_t) (addr + data_len - 1);On 32-bit ESP32 targets The blockdev wrapper adds no value here — it just forwards to --- a/src/platforms/esp32/components/avm_builtins/storage_nif.c
+++ b/src/platforms/esp32/components/avm_builtins/storage_nif.c
@@
-#include <soc/soc_caps.h>
-#if ESP_IDF_VERSION_MAJOR >= 6 && defined(CONFIG_AVM_ENABLE_RAW_SDCARD_NIFS)
-#include <esp_blockdev.h>
-#endif
+#include <soc/soc_caps.h>
@@ struct SDCardBlockDevice
sdmmc_card_t *card;
sdspi_dev_handle_t spi_handle;
-#if ESP_IDF_VERSION_MAJOR >= 6
- esp_blockdev_handle_t blockdev;
-#endif
};
@@ static esp_err_t sdcard_blockdev_read(struct SDCardBlockDevice *dev, void *dst, size_t sector)
{
-#if ESP_IDF_VERSION_MAJOR >= 6
- return dev->blockdev->ops->read(dev->blockdev, dst, dev->sector_size,
- (uint64_t) sector * dev->sector_size, dev->sector_size);
-#else
return sdmmc_read_sectors(dev->card, dst, sector, 1);
-#endif
}
@@ static esp_err_t sdcard_blockdev_write(
{
-#if ESP_IDF_VERSION_MAJOR >= 6
- return dev->blockdev->ops->write(
- dev->blockdev, src, (uint64_t) sector * dev->sector_size, dev->sector_size);
-#else
return sdmmc_write_sectors(dev->card, src, sector, 1);
-#endif
}
@@ static esp_err_t sdcard_blockdev_close(struct SDCardBlockDevice *dev)
esp_err_t ret = ESP_OK;
-
-#if ESP_IDF_VERSION_MAJOR >= 6
- if (dev->blockdev) {
- dev->blockdev->ops->release(dev->blockdev);
- dev->blockdev = NULL;
- }
-#endif
if (dev->interface == SDCardSDSPI) {
@@ static esp_err_t sdcard_blockdev_init(struct SDCardConfig *cfg, struct SDCardBlockDevice *dev)
dev->sector_size = dev->card->csd.sector_size;
dev->sector_count = dev->card->csd.capacity;
-
-#if ESP_IDF_VERSION_MAJOR >= 6
- err = sdmmc_get_blockdev(dev->card, &dev->blockdev);
- if (UNLIKELY(err != ESP_OK)) {
- dev->blockdev = NULL;
- sdcard_blockdev_close(dev);
- return err;
- }
-#endif
return ESP_OK;
}…and drop the now-unused initializer in @@ nif_esp_sdcard_open
dev->sector_count = 0;
-#if ESP_IDF_VERSION_MAJOR >= 6
- dev->blockdev = NULL;
-#endif2. 🟠 Should-fix — resource leak in
|
These changes are made under both the "Apache 2.0" and the "GNU Lesser General
Public License 2.1 or later" license terms (dual license).
SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later