Fixes and improvements

This commit is contained in:
Ken Van Hoeylandt 2026-03-03 21:41:48 +01:00
parent d63a401cd5
commit e4cf91aa18
12 changed files with 87 additions and 56 deletions

View File

@ -1,5 +1,4 @@
#include "devices/Display.h"
#include "devices/Sdcard.h"
#include <Tactility/hal/Configuration.h>
@ -9,8 +8,7 @@ using namespace tt::hal;
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
return {
createDisplay(),
createSdCard()
createDisplay()
};
}

View File

@ -1,22 +0,0 @@
#include "Sdcard.h"
#include <Tactility/hal/sdcard/SdmmcDevice.h>
#include <Tactility/lvgl/LvglSync.h>
using tt::hal::sdcard::SdmmcDevice;
std::shared_ptr<SdCardDevice> createSdCard() {
auto configuration = std::make_unique<SdmmcDevice::Config>(
GPIO_NUM_12,
GPIO_NUM_16,
GPIO_NUM_14,
GPIO_NUM_17,
GPIO_NUM_21,
GPIO_NUM_18,
SdCardDevice::MountBehaviour::AtBoot
);
return std::make_shared<SdmmcDevice>(
std::move(configuration)
);
}

View File

@ -1,7 +0,0 @@
#pragma once
#include "Tactility/hal/sdcard/SdCardDevice.h"
using tt::hal::sdcard::SdCardDevice;
std::shared_ptr<SdCardDevice> createSdCard();

View File

@ -22,3 +22,4 @@ dpi=186
[lvgl]
colorDepth=16
uiDensity=compact
fontSize=10

View File

@ -32,15 +32,14 @@
};
sdmmc0 {
compatible = "espressif,sdmmc";
pin-clk = <&gpio 12 GPIO_FLAG_NONE>;
pin-cmd = <&gpio 16 GPIO_FLAG_NONE>;
pin-d0 = <&gpio 14 GPIO_FLAG_NONE>;
pin-d1 = <&gpio 17 GPIO_FLAG_NONE>;
pin-d2 = <&gpio 21 GPIO_FLAG_NONE>;
pin-d3 = <&gpio 18 GPIO_FLAG_NONE>;
compatible = "espressif,esp32-sdmmc";
pin-clk = <&gpio0 12 GPIO_FLAG_NONE>;
pin-cmd = <&gpio0 16 GPIO_FLAG_NONE>;
pin-d0 = <&gpio0 14 GPIO_FLAG_NONE>;
pin-d1 = <&gpio0 17 GPIO_FLAG_NONE>;
pin-d2 = <&gpio0 21 GPIO_FLAG_NONE>;
pin-d3 = <&gpio0 18 GPIO_FLAG_NONE>;
bus-width = <4>;
max-open-files = <4>;
};
stemma_qt: uart1 {

View File

@ -1,6 +1,6 @@
description: ESP32 SDMMC
compatible: "espressif,sdmmc"
compatible: "espressif,esp32-sdmmc"
properties:
pin-clk:
@ -43,10 +43,6 @@ properties:
type: int
required: true
description: Bus width in bits
max-open-files:
type: int
required: true
description: Maximum number of open files
wp-active-high:
type: boolean
default: false

View File

@ -23,7 +23,6 @@ struct Esp32SdmmcConfig {
struct GpioPinSpec pin_cd;
struct GpioPinSpec pin_wp;
uint8_t bus_width;
uint8_t max_open_files;
bool wp_active_high;
bool enable_uhs;
};

View File

@ -7,7 +7,6 @@
#include "tactility/drivers/gpio_descriptor.h"
#include <new>
#include <tactility/drivers/esp32_gpio_helpers.h>
#include <tactility/drivers/esp32_gpio_fs.h>
#define TAG "esp32_sdmmc"
@ -135,7 +134,7 @@ static error_t stop(Device* device) {
extern Module platform_esp32_module;
Driver esp32_spi_driver = {
Driver esp32_sdmmc_driver = {
.name = "esp32_sdmmc",
.compatible = (const char*[]) { "espressif,esp32-sdmmc", nullptr },
.start_device = start,

View File

@ -2,6 +2,7 @@
#include <tactility/device.h>
#include <tactility/drivers/esp32_sdmmc.h>
#include <tactility/drivers/file_system.h>
#include <tactility/drivers/gpio_descriptor.h>
#include <tactility/log.h>
#include <driver/sdmmc_host.h>
@ -9,7 +10,10 @@
#include <new>
#include <sdmmc_cmd.h>
#include <string>
#include <tactility/drivers/gpio_descriptor.h>
#if SOC_SD_PWR_CTRL_SUPPORTED
#include <sd_pwr_ctrl_by_on_chip_ldo.h>
#endif
#define TAG "esp32_sdmmc_fs"
@ -20,6 +24,9 @@
struct Esp32SdmmcFsInternal {
std::string mount_path {};
sdmmc_card_t* card = nullptr;
#if SOC_SD_PWR_CTRL_SUPPORTED
sd_pwr_ctrl_handle_t pwr_ctrl_handle = nullptr;
#endif
};
static gpio_num_t to_native_pin(GpioPinSpec pin_spec) {
@ -37,7 +44,7 @@ error_t mount(Device* device, const char* mount_path) {
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
.format_if_mount_failed = false,
.max_files = config->max_open_files,
.max_files = 4,
.allocation_unit_size = 0, // Default is sector size
.disk_status_check_enable = false,
.use_one_fat = false
@ -45,6 +52,18 @@ error_t mount(Device* device, const char* mount_path) {
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
#if SOC_SD_PWR_CTRL_SUPPORTED
sd_pwr_ctrl_ldo_config_t ldo_config = {
.ldo_chan_id = 4, // LDO4 is typically used for SDMMC on ESP32-S3
};
esp_err_t pwr_err = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &data->pwr_ctrl_handle);
if (pwr_err != ESP_OK) {
LOG_E(TAG, "Failed to create SD power control driver, err=0x%x", pwr_err);
return ERROR_NOT_SUPPORTED;
}
host.pwr_ctrl_handle = data->pwr_ctrl_handle;
#endif
uint32_t slot_config_flags = 0;
if (config->enable_uhs) slot_config_flags |= SDMMC_SLOT_FLAG_UHS1;
if (config->wp_active_high) slot_config_flags |= SDMMC_SLOT_FLAG_WP_ACTIVE_HIGH;
@ -74,9 +93,16 @@ error_t mount(Device* device, const char* mount_path) {
} else {
LOG_E(TAG, "Mounting failed: %s", esp_err_to_name(result));
}
#if SOC_SD_PWR_CTRL_SUPPORTED
if (data->pwr_ctrl_handle) {
sd_pwr_ctrl_del_on_chip_ldo(data->pwr_ctrl_handle);
data->pwr_ctrl_handle = nullptr;
}
#endif
return ERROR_UNDEFINED;
}
LOG_I(TAG, "Mounted %s", mount_path);
data->mount_path = mount_path;
return ERROR_NONE;
@ -94,6 +120,13 @@ error_t unmount(Device* device) {
data->mount_path = "";
data->card = nullptr;
#if SOC_SD_PWR_CTRL_SUPPORTED
if (data->pwr_ctrl_handle) {
sd_pwr_ctrl_del_on_chip_ldo(data->pwr_ctrl_handle);
data->pwr_ctrl_handle = nullptr;
}
#endif
return ERROR_NONE;
}

View File

@ -26,6 +26,8 @@
#include <Tactility/StringUtils.h>
#include <ranges>
#include <tactility/drivers/file_system.h>
#include <tactility/drivers/hal_device.h>
#if TT_FEATURE_SCREENSHOT_ENABLED
#include <lv_screenshot.h>
@ -774,6 +776,16 @@ esp_err_t WebServerService::handleFsList(httpd_req_t* request) {
break;
}
}
device_for_each_of_type(&FILE_SYSTEM_TYPE, &json, [] (auto* fs_device, void* context) {
if (file_system_is_mounted(fs_device)) {
auto* json_context_ptr = static_cast<std::ostringstream*>(context);
auto& json_context = *json_context_ptr;
json_context << ",{\"name\":\"sdcard\",\"type\":\"dir\",\"size\":0}";
}
return true;
});
json << "]}";
} else {
std::vector<dirent> entries;
@ -1180,6 +1192,29 @@ esp_err_t WebServerService::handleApiSysinfo(httpd_req_t* request) {
break;
}
}
struct FsIterContext {
std::ostringstream& json;
bool sdcard_found;
};
FsIterContext fs_iter_context { json, sdcard_found };
device_for_each_of_type(&FILE_SYSTEM_TYPE, &fs_iter_context, [] (auto* fs_device, void* context) {
if (!file_system_is_mounted(fs_device)) return true;
char mount_path[128];
if (file_system_get_mount_path(fs_device, mount_path, sizeof(mount_path)) != ESP_OK) return true;
uint64_t storage_total = 0, storage_free = 0;
if (esp_vfs_fat_info(mount_path, &storage_total, &storage_free) != ESP_OK) return true;
auto* fs_iter_context = static_cast<FsIterContext*>(context);
auto& json_context = fs_iter_context->json;
json_context << "\"free\":" << storage_free << ",";
json_context << "\"total\":" << storage_total << ",";
json_context << "\"mounted\":true";
fs_iter_context->sdcard_found = true;
return true;
});
if (fs_iter_context.sdcard_found) sdcard_found = true;
if (!sdcard_found) {
json << "\"mounted\":false";
}

View File

@ -20,13 +20,13 @@ struct FileSystemApi {
extern const struct DeviceType FILE_SYSTEM_TYPE;
error_t file_system_mount(struct Device* device);
error_t file_system_mount(struct Device* device, const char* mount_path);
error_t file_system_unmount(struct Device* device);
bool file_system_is_mounted(struct Device* device);
error_t file_system_get_mount_path(struct Device*, char* out_path);
error_t file_system_get_mount_path(struct Device*, char* out_path, size_t out_path_size);
#ifdef __cplusplus
}

View File

@ -5,9 +5,9 @@
extern "C" {
error_t file_system_mount(Device* device) {
error_t file_system_mount(Device* device, const char* mount_path) {
const auto* driver = device_get_driver(device);
return INTERNAL_API(driver)->mount(device);
return INTERNAL_API(driver)->mount(device, mount_path);
}
error_t file_system_unmount(Device* device) {
@ -20,9 +20,9 @@ bool file_system_is_mounted(Device* device) {
return INTERNAL_API(driver)->is_mounted(device);
}
error_t file_system_get_mount_path(Device* device, char* out_path) {
error_t file_system_get_mount_path(Device* device, char* out_path, size_t out_path_size) {
const auto* driver = device_get_driver(device);
return INTERNAL_API(driver)->get_mount_path(device, out_path);
return INTERNAL_API(driver)->get_mount_path(device, out_path, out_path_size);
}
const DeviceType FILE_SYSTEM_TYPE {