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

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] [lvgl]
colorDepth=16 colorDepth=16
uiDensity=compact uiDensity=compact
fontSize=10

View File

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

View File

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

View File

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

View File

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

View File

@ -2,6 +2,7 @@
#include <tactility/device.h> #include <tactility/device.h>
#include <tactility/drivers/esp32_sdmmc.h> #include <tactility/drivers/esp32_sdmmc.h>
#include <tactility/drivers/file_system.h> #include <tactility/drivers/file_system.h>
#include <tactility/drivers/gpio_descriptor.h>
#include <tactility/log.h> #include <tactility/log.h>
#include <driver/sdmmc_host.h> #include <driver/sdmmc_host.h>
@ -9,7 +10,10 @@
#include <new> #include <new>
#include <sdmmc_cmd.h> #include <sdmmc_cmd.h>
#include <string> #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" #define TAG "esp32_sdmmc_fs"
@ -20,6 +24,9 @@
struct Esp32SdmmcFsInternal { struct Esp32SdmmcFsInternal {
std::string mount_path {}; std::string mount_path {};
sdmmc_card_t* card = nullptr; 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) { 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 = { esp_vfs_fat_sdmmc_mount_config_t mount_config = {
.format_if_mount_failed = false, .format_if_mount_failed = false,
.max_files = config->max_open_files, .max_files = 4,
.allocation_unit_size = 0, // Default is sector size .allocation_unit_size = 0, // Default is sector size
.disk_status_check_enable = false, .disk_status_check_enable = false,
.use_one_fat = 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(); 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; uint32_t slot_config_flags = 0;
if (config->enable_uhs) slot_config_flags |= SDMMC_SLOT_FLAG_UHS1; 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; 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 { } else {
LOG_E(TAG, "Mounting failed: %s", esp_err_to_name(result)); 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; return ERROR_UNDEFINED;
} }
LOG_I(TAG, "Mounted %s", mount_path);
data->mount_path = mount_path; data->mount_path = mount_path;
return ERROR_NONE; return ERROR_NONE;
@ -94,6 +120,13 @@ error_t unmount(Device* device) {
data->mount_path = ""; data->mount_path = "";
data->card = nullptr; 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; return ERROR_NONE;
} }

View File

@ -26,6 +26,8 @@
#include <Tactility/StringUtils.h> #include <Tactility/StringUtils.h>
#include <ranges> #include <ranges>
#include <tactility/drivers/file_system.h>
#include <tactility/drivers/hal_device.h>
#if TT_FEATURE_SCREENSHOT_ENABLED #if TT_FEATURE_SCREENSHOT_ENABLED
#include <lv_screenshot.h> #include <lv_screenshot.h>
@ -774,6 +776,16 @@ esp_err_t WebServerService::handleFsList(httpd_req_t* request) {
break; 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 << "]}"; json << "]}";
} else { } else {
std::vector<dirent> entries; std::vector<dirent> entries;
@ -1180,6 +1192,29 @@ esp_err_t WebServerService::handleApiSysinfo(httpd_req_t* request) {
break; 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) { if (!sdcard_found) {
json << "\"mounted\":false"; json << "\"mounted\":false";
} }

View File

@ -20,13 +20,13 @@ struct FileSystemApi {
extern const struct DeviceType FILE_SYSTEM_TYPE; 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); error_t file_system_unmount(struct Device* device);
bool file_system_is_mounted(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 #ifdef __cplusplus
} }

View File

@ -5,9 +5,9 @@
extern "C" { 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); 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) { 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); 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); 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 { const DeviceType FILE_SYSTEM_TYPE {