Driver improvements (#535)
- New drivers: - SD SPI - spi_peripheral - touch_placeholder - display_placeholder - Devicetree compiler: - Implement phandle-arrays - Implement device addresses - Add placeholder drivers to all devices with a SPI display - SPI driver: add `cs-pins` and set them to high on driver start - FileSystem: add `file_system_set_owner()` and `file_system_get_owner()` - File locking is now checking if the related `FileSystem` is part of a shared SPI bus - Add `device_get_child_count()` - SDMMC driver: Remove default of `slot` value - Fix for Crowpanel Basic 3.5" display (add delay to booting) - Fix for LilyGO T-HMI SD card mounting (delayed mounting by disabling it initially in the dts)
This commit is contained in:
committed by
GitHub
parent
e50659a3fb
commit
599fa46766
@@ -1,84 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <tactility/hal/Device.h>
|
||||
|
||||
#include <Tactility/Lock.h>
|
||||
#include <Tactility/TactilityCore.h>
|
||||
|
||||
|
||||
struct FileSystem;
|
||||
namespace tt::hal::sdcard {
|
||||
|
||||
/**
|
||||
* Warning: getLock() does not have to be used when calling any of the functions of this class.
|
||||
* The lock is only used for file access on the path where the SD card is mounted.
|
||||
* This is mainly used when accessing the SD card on a shared SPI bus.
|
||||
*/
|
||||
class SdCardDevice : public Device {
|
||||
|
||||
public:
|
||||
|
||||
enum class State {
|
||||
Mounted,
|
||||
Unmounted,
|
||||
Error,
|
||||
Timeout // Failed to retrieve state due to timeout
|
||||
};
|
||||
|
||||
enum class MountBehaviour {
|
||||
AtBoot, /** Only mount at boot */
|
||||
Anytime /** Mount/dismount any time */
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
MountBehaviour mountBehaviour;
|
||||
FileSystem* fileSystem;
|
||||
|
||||
public:
|
||||
|
||||
explicit SdCardDevice(MountBehaviour mountBehaviour);
|
||||
~SdCardDevice() override;
|
||||
|
||||
Type getType() const final { return Type::SdCard; };
|
||||
|
||||
/**
|
||||
* Mount the device.
|
||||
* @param mountPath the path to mount at
|
||||
* @return true on successful mount
|
||||
*/
|
||||
virtual bool mount(const std::string& mountPath) = 0;
|
||||
|
||||
/**
|
||||
* Unmount the device.
|
||||
* @return true on successful unmount
|
||||
*/
|
||||
virtual bool unmount() = 0;
|
||||
|
||||
virtual State getState(TickType_t timeout = kernel::MAX_TICKS) const = 0;
|
||||
|
||||
/** @return empty string when not mounted or the mount path if mounted */
|
||||
virtual std::string getMountPath() const = 0;
|
||||
|
||||
/** @return non-null lock, used by code that wants to access files on the mount path of this SD card */
|
||||
virtual std::shared_ptr<Lock> getLock() const = 0;
|
||||
|
||||
/** @return the MountBehaviour of this device */
|
||||
virtual MountBehaviour getMountBehaviour() const { return mountBehaviour; }
|
||||
|
||||
/** @return true if the SD card was mounted, returns false when it was not or when a timeout happened. */
|
||||
bool isMounted(TickType_t timeout = kernel::MAX_TICKS) const { return getState(timeout) == State::Mounted; }
|
||||
};
|
||||
|
||||
/** Return the SdCard device if the path is within the SdCard mounted path (path std::string::starts_with() check), otherwise return nullptr */
|
||||
std::shared_ptr<SdCardDevice> find(const std::string& path);
|
||||
|
||||
/**
|
||||
* Attempt to find an SD card that the specified belongs to,
|
||||
* and returns its lock if the SD card is mounted. Otherwise it returns nullptr.
|
||||
* @param[in] a path on a file system (e.g. file, directory, etc.)
|
||||
* @return the lock of a mounted SD card or otherwise null
|
||||
*/
|
||||
std::shared_ptr<Lock> findSdCardLock(const std::string& path);
|
||||
|
||||
} // namespace tt::hal
|
||||
@@ -1,104 +0,0 @@
|
||||
#ifdef ESP_PLATFORM
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SdCardDevice.h"
|
||||
#include "Tactility/kernel/SpiDeviceLock.h"
|
||||
|
||||
#include <driver/gpio.h>
|
||||
#include <driver/spi_common.h>
|
||||
|
||||
#include <sd_protocol_types.h>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace tt::hal::sdcard {
|
||||
|
||||
/**
|
||||
* SD card interface at the default SPI interface
|
||||
*/
|
||||
class SpiSdCardDevice final : public SdCardDevice {
|
||||
|
||||
public:
|
||||
|
||||
struct Config {
|
||||
Config(
|
||||
gpio_num_t spiPinCs,
|
||||
gpio_num_t spiPinCd,
|
||||
gpio_num_t spiPinWp,
|
||||
gpio_num_t spiPinInt,
|
||||
MountBehaviour mountBehaviourAtBoot,
|
||||
/** When customLock is a nullptr, use the SPI default one */
|
||||
std::shared_ptr<Lock> customLock = nullptr,
|
||||
std::vector<gpio_num_t> csPinWorkAround = std::vector<gpio_num_t>(),
|
||||
spi_host_device_t spiHost = SPI2_HOST,
|
||||
int spiFrequencyKhz = SDMMC_FREQ_DEFAULT
|
||||
) : spiFrequencyKhz(spiFrequencyKhz),
|
||||
spiPinCs(spiPinCs),
|
||||
spiPinCd(spiPinCd),
|
||||
spiPinWp(spiPinWp),
|
||||
spiPinInt(spiPinInt),
|
||||
mountBehaviourAtBoot(mountBehaviourAtBoot),
|
||||
customLock(customLock ? std::move(customLock) : nullptr),
|
||||
csPinWorkAround(std::move(csPinWorkAround)),
|
||||
spiHost(spiHost)
|
||||
{}
|
||||
|
||||
int spiFrequencyKhz;
|
||||
gpio_num_t spiPinCs; // Clock
|
||||
gpio_num_t spiPinCd; // Card detect
|
||||
gpio_num_t spiPinWp; // Write-protect
|
||||
gpio_num_t spiPinInt; // Interrupt
|
||||
MountBehaviour mountBehaviourAtBoot;
|
||||
std::shared_ptr<Lock> customLock; // can be nullptr
|
||||
std::vector<gpio_num_t> csPinWorkAround;
|
||||
spi_host_device_t spiHost;
|
||||
bool formatOnMountFailed = false;
|
||||
uint16_t maxOpenFiles = 4;
|
||||
uint16_t allocUnitSize = 16 * 1024;
|
||||
bool statusCheckEnabled = false;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
std::string mountPath;
|
||||
sdmmc_card_t* card = nullptr;
|
||||
std::shared_ptr<Config> config;
|
||||
std::shared_ptr<Lock> lock;
|
||||
|
||||
bool applyGpioWorkAround();
|
||||
bool mountInternal(const std::string& mountPath);
|
||||
|
||||
public:
|
||||
|
||||
explicit SpiSdCardDevice(std::unique_ptr<Config> newConfig, ::Device* spiController) : SdCardDevice(newConfig->mountBehaviourAtBoot),
|
||||
config(std::move(newConfig))
|
||||
{
|
||||
if (config->customLock == nullptr) {
|
||||
auto spi_lock = std::make_shared<SpiDeviceLock>(spiController);
|
||||
lock = std::static_pointer_cast<Lock>(spi_lock);
|
||||
} else {
|
||||
lock = config->customLock;
|
||||
}
|
||||
}
|
||||
|
||||
std::string getName() const override { return "SD Card"; }
|
||||
std::string getDescription() const override { return "SD card via SPI interface"; }
|
||||
|
||||
bool mount(const std::string& mountPath) override;
|
||||
bool unmount() override;
|
||||
std::string getMountPath() const override { return mountPath; }
|
||||
|
||||
std::shared_ptr<Lock> getLock() const override {
|
||||
return lock;
|
||||
}
|
||||
|
||||
State getState(TickType_t timeout) const override;
|
||||
|
||||
/** return card when mounted, otherwise return nullptr */
|
||||
sdmmc_card_t* getCard() { return card; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Tactility/Lock.h>
|
||||
|
||||
namespace tt::hal::sdcard {
|
||||
|
||||
/**
|
||||
* Attempt to find an SD card that the specified belongs to,
|
||||
* and returns its lock if the SD card is mounted. Otherwise it returns nullptr.
|
||||
* @param[in] a path on a file system (e.g. file, directory, etc.)
|
||||
* @return the lock of a mounted SD card or otherwise null
|
||||
*/
|
||||
std::shared_ptr<Lock> findSdCardLock(const std::string& path);
|
||||
|
||||
void mountAll();
|
||||
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace tt::hal::sdcard {
|
||||
|
||||
void mountAll();
|
||||
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <Tactility/file/File.h>
|
||||
#include <Tactility/file/FileLock.h>
|
||||
#include <Tactility/hal/sdcard/SdCardDevice.h>
|
||||
#include <Tactility/Logger.h>
|
||||
#include <Tactility/LogMessages.h>
|
||||
#include <Tactility/MountPoints.h>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "Tactility/app/fileselection/State.h"
|
||||
|
||||
#include <Tactility/file/File.h>
|
||||
#include "Tactility/hal/sdcard/SdCardDevice.h"
|
||||
#include <Tactility/Logger.h>
|
||||
#include <Tactility/MountPoints.h>
|
||||
#include <Tactility/kernel/Platform.h>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "Tactility/file/FileLock.h"
|
||||
|
||||
#include <Tactility/hal/sdcard/SdCardDevice.h>
|
||||
#include <Tactility/Mutex.h>
|
||||
#include <Tactility/hal/SdCard.h>
|
||||
|
||||
namespace tt::file {
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <tactility/hal/Device.h>
|
||||
|
||||
#include <Tactility/hal/display/DisplayDevice.h>
|
||||
#include <Tactility/hal/sdcard/SdCardMounting.h>
|
||||
#include <Tactility/hal/SdCard.h>
|
||||
#include <Tactility/hal/touch/TouchDevice.h>
|
||||
#include <Tactility/kernel/SystemEvents.h>
|
||||
|
||||
|
||||
@@ -1,26 +1,50 @@
|
||||
#include <tactility/hal/Device.h>
|
||||
#include "Tactility/hal/sdcard/SdCardDevice.h"
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/drivers/sdcard.h>
|
||||
#include <tactility/filesystem/file_system.h>
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace tt::hal::sdcard {
|
||||
|
||||
std::shared_ptr<SdCardDevice> find(const std::string& path) {
|
||||
auto sdcards = findDevices<SdCardDevice>(Device::Type::SdCard);
|
||||
for (auto& sdcard : sdcards) {
|
||||
if (sdcard->isMounted() && path.starts_with(sdcard->getMountPath())) {
|
||||
return sdcard;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<Lock> findSdCardLock(const std::string& path) {
|
||||
auto sdcard = find(path);
|
||||
if (sdcard != nullptr) {
|
||||
return sdcard->getLock();
|
||||
}
|
||||
struct Ctx {
|
||||
const std::string& path;
|
||||
std::shared_ptr<Lock> result;
|
||||
};
|
||||
Ctx ctx = { path, nullptr };
|
||||
|
||||
return nullptr;
|
||||
file_system_for_each(&ctx, [](FileSystem* fs, void* context) {
|
||||
auto* c = static_cast<Ctx*>(context);
|
||||
char mount_path[64];
|
||||
if (file_system_get_path(fs, mount_path, sizeof(mount_path)) != ERROR_NONE) return true;
|
||||
if (!c->path.starts_with(mount_path)) return true;
|
||||
|
||||
auto* owner = file_system_get_owner(fs);
|
||||
if (owner != nullptr) {
|
||||
// Check for I2C controller: if it has more than 2 children, assume it's the display
|
||||
// TODO: Improve this
|
||||
auto* parent = device_get_parent(owner);
|
||||
if (parent != nullptr && device_get_child_count(parent) >= 2) {
|
||||
c->result = lvgl::getSyncLock();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
return ctx.result;
|
||||
}
|
||||
|
||||
void mountAll() {
|
||||
device_for_each_of_type(&SDCARD_TYPE, nullptr, [](::Device* device, void*) -> bool {
|
||||
if (!device_is_ready(device)) {
|
||||
if (device_start(device) != ERROR_NONE) {
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
#include <Tactility/hal/sdcard/SdCardDevice.h>
|
||||
|
||||
#include <tactility/filesystem/file_system.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace tt::hal::sdcard {
|
||||
|
||||
static error_t mount(void* data) {
|
||||
auto* device = static_cast<SdCardDevice*>(data);
|
||||
auto path = device->getMountPath();
|
||||
if (!device->mount(path)) return ERROR_UNDEFINED;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static error_t unmount(void* data) {
|
||||
auto* device = static_cast<SdCardDevice*>(data);
|
||||
if (!device->unmount()) return ERROR_UNDEFINED;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static bool is_mounted(void* data) {
|
||||
auto* device = static_cast<SdCardDevice*>(data);
|
||||
return device->isMounted();
|
||||
}
|
||||
|
||||
static error_t get_path(void* data, char* out_path, size_t out_path_size) {
|
||||
auto* device = static_cast<SdCardDevice*>(data);
|
||||
const auto mount_path = device->getMountPath();
|
||||
if (mount_path.size() >= out_path_size) return ERROR_BUFFER_OVERFLOW;
|
||||
if (mount_path.empty()) return ERROR_INVALID_STATE;
|
||||
strncpy(out_path, mount_path.c_str(), out_path_size);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
FileSystemApi sdCardDeviceApi = {
|
||||
.mount = mount,
|
||||
.unmount = unmount,
|
||||
.is_mounted = is_mounted,
|
||||
.get_path = get_path
|
||||
};
|
||||
|
||||
SdCardDevice::SdCardDevice(MountBehaviour mountBehaviour) : mountBehaviour(mountBehaviour) {
|
||||
fileSystem = file_system_add(&sdCardDeviceApi, this);
|
||||
check(fileSystem != nullptr);
|
||||
}
|
||||
|
||||
SdCardDevice::~SdCardDevice() {
|
||||
file_system_remove(fileSystem);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
#include <Tactility/hal/sdcard/SdCardMounting.h>
|
||||
#include <Tactility/hal/sdcard/SdCardDevice.h>
|
||||
|
||||
#include <Tactility/Logger.h>
|
||||
|
||||
#include <format>
|
||||
|
||||
namespace tt::hal::sdcard {
|
||||
|
||||
static const auto LOGGER = Logger("SdCardMounting");
|
||||
constexpr auto* TT_SDCARD_MOUNT_POINT = "/sdcard";
|
||||
|
||||
static void mount(const std::shared_ptr<SdCardDevice>& sdcard, const std::string& path) {
|
||||
LOGGER.info("Mounting sdcard at {}", path);
|
||||
if (!sdcard->mount(path)) {
|
||||
LOGGER.warn("SD card mount failed for {} (init can continue)", path);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string getMountPath(int index, int count) {
|
||||
return (count == 1) ? TT_SDCARD_MOUNT_POINT : std::format("{}{}", TT_SDCARD_MOUNT_POINT, index);
|
||||
}
|
||||
|
||||
void mountAll() {
|
||||
const auto sdcards = hal::findDevices<SdCardDevice>(Device::Type::SdCard);
|
||||
// Numbered mount path name
|
||||
for (int i = 0; i < sdcards.size(); i++) {
|
||||
auto sdcard = sdcards[i];
|
||||
if (!sdcard->isMounted() && sdcard->getMountBehaviour() == SdCardDevice::MountBehaviour::AtBoot) {
|
||||
std::string mount_path = getMountPath(i, sdcards.size());
|
||||
mount(sdcard, mount_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
#ifdef ESP_PLATFORM
|
||||
|
||||
#include <Tactility/hal/gpio/Gpio.h>
|
||||
#include <Tactility/hal/sdcard/SpiSdCardDevice.h>
|
||||
#include <Tactility/Logger.h>
|
||||
|
||||
#include <esp_vfs_fat.h>
|
||||
#include <sdmmc_cmd.h>
|
||||
|
||||
namespace tt::hal::sdcard {
|
||||
|
||||
static const auto LOGGER = Logger("SpiSdCardDevice");
|
||||
|
||||
/**
|
||||
* Before we can initialize the sdcard's SPI communications, we have to set all
|
||||
* other SPI pins on the board high.
|
||||
* See https://github.com/espressif/esp-idf/issues/1597
|
||||
* See https://github.com/Xinyuan-LilyGO/T-Deck/blob/master/examples/UnitTest/UnitTest.ino
|
||||
* @return success result
|
||||
*/
|
||||
bool SpiSdCardDevice::applyGpioWorkAround() {
|
||||
LOGGER.info("applyGpioWorkAround");
|
||||
|
||||
uint64_t pin_bit_mask = config->spiPinCs != GPIO_NUM_NC ? BIT64(config->spiPinCs) : 0;
|
||||
for (auto const& pin: config->csPinWorkAround) {
|
||||
pin_bit_mask |= BIT64(pin);
|
||||
}
|
||||
|
||||
// Nothing to do
|
||||
if (pin_bit_mask == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!gpio::configureWithPinBitmask(pin_bit_mask, gpio::Mode::Output, false, false)) {
|
||||
LOGGER.error("GPIO work-around failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto const& pin: config->csPinWorkAround) {
|
||||
if (!gpio::setLevel(pin, true)) {
|
||||
LOGGER.error("Failed to set board CS pin high");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SpiSdCardDevice::mountInternal(const std::string& newMountPath) {
|
||||
LOGGER.info("Mounting {}", newMountPath);
|
||||
|
||||
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
||||
.format_if_mount_failed = config->formatOnMountFailed,
|
||||
.max_files = config->maxOpenFiles,
|
||||
.allocation_unit_size = config->allocUnitSize,
|
||||
.disk_status_check_enable = config->statusCheckEnabled,
|
||||
.use_one_fat = false
|
||||
};
|
||||
|
||||
// Init without card detect (CD) and write protect (WD)
|
||||
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
|
||||
slot_config.host_id = config->spiHost;
|
||||
slot_config.gpio_cs = config->spiPinCs;
|
||||
slot_config.gpio_cd = config->spiPinCd;
|
||||
slot_config.gpio_wp = config->spiPinWp;
|
||||
slot_config.gpio_int = config->spiPinInt;
|
||||
|
||||
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
|
||||
// The following value is from T-Deck repo's UnitTest.ino project:
|
||||
// https://github.com/Xinyuan-LilyGO/T-Deck/blob/master/examples/UnitTest/UnitTest.ino
|
||||
// Observation: Using this automatically sets the bus to 20MHz
|
||||
host.max_freq_khz = config->spiFrequencyKhz;
|
||||
host.slot = config->spiHost;
|
||||
|
||||
esp_err_t result = esp_vfs_fat_sdspi_mount(newMountPath.c_str(), &host, &slot_config, &mount_config, &card);
|
||||
|
||||
if (result != ESP_OK || card == nullptr) {
|
||||
if (result == ESP_FAIL) {
|
||||
LOGGER.error("Mounting failed. Ensure the card is formatted with FAT.");
|
||||
} else {
|
||||
LOGGER.error("Mounting failed ({})", esp_err_to_name(result));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
mountPath = newMountPath;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SpiSdCardDevice::mount(const std::string& newMountPath) {
|
||||
auto lock = getLock()->asScopedLock();
|
||||
lock.lock();
|
||||
|
||||
if (!applyGpioWorkAround()) {
|
||||
LOGGER.error("Failed to apply GPIO work-around");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mountInternal(newMountPath)) {
|
||||
LOGGER.info("Mounted at {}", newMountPath);
|
||||
sdmmc_card_print_info(stdout, card);
|
||||
return true;
|
||||
} else {
|
||||
LOGGER.error("Mount failed for {}", newMountPath);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SpiSdCardDevice::unmount() {
|
||||
auto lock = getLock()->asScopedLock();
|
||||
lock.lock();
|
||||
|
||||
if (card == nullptr) {
|
||||
LOGGER.error("Can't unmount: not mounted");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (esp_vfs_fat_sdcard_unmount(mountPath.c_str(), card) != ESP_OK) {
|
||||
LOGGER.error("Unmount failed for {}", mountPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGGER.info("Unmounted {}", mountPath);
|
||||
mountPath = "";
|
||||
card = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Refactor to "bool getStatus(Status* status)" method so that it can fail when the lvgl lock fails
|
||||
SdCardDevice::State SpiSdCardDevice::getState(TickType_t timeout) const {
|
||||
if (card == nullptr) {
|
||||
return State::Unmounted;
|
||||
}
|
||||
|
||||
/**
|
||||
* The SD card and the screen are on the same SPI bus.
|
||||
* Writing and reading to the bus from 2 devices at the same time causes crashes.
|
||||
* This work-around ensures that this check is only happening when LVGL isn't rendering.
|
||||
*/
|
||||
auto lock = getLock()->asScopedLock();
|
||||
bool locked = lock.lock(timeout);
|
||||
if (!locked) {
|
||||
return State::Timeout;
|
||||
}
|
||||
|
||||
if (sdmmc_get_status(card) != ESP_OK) {
|
||||
return State::Error;
|
||||
}
|
||||
|
||||
return State::Mounted;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -3,11 +3,12 @@
|
||||
#include <soc/soc_caps.h>
|
||||
|
||||
#include <Tactility/hal/usb/Usb.h>
|
||||
#include <Tactility/hal/sdcard/SpiSdCardDevice.h>
|
||||
#include <Tactility/hal/usb/UsbTusb.h>
|
||||
|
||||
#include <Tactility/Logger.h>
|
||||
#include <tactility/drivers/esp32_sdmmc.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/esp32_sdcard.h>
|
||||
|
||||
namespace tt::hal::usb {
|
||||
|
||||
@@ -24,41 +25,23 @@ static Mode currentMode = Mode::Default;
|
||||
static RTC_NOINIT_ATTR BootModeData bootModeData;
|
||||
|
||||
sdmmc_card_t* getCard() {
|
||||
sdmmc_card_t* sdcard = nullptr;
|
||||
sdmmc_card_t* card = nullptr;
|
||||
|
||||
// Find old HAL SD card device:
|
||||
auto sdcards = findDevices<sdcard::SpiSdCardDevice>(Device::Type::SdCard);
|
||||
for (auto& device : sdcards) {
|
||||
auto sdcard_device= std::static_pointer_cast<sdcard::SpiSdCardDevice>(device);
|
||||
if (sdcard_device != nullptr && sdcard_device->isMounted() && sdcard_device->getCard() != nullptr) {
|
||||
sdcard = sdcard_device->getCard();
|
||||
break;
|
||||
}
|
||||
}
|
||||
device_for_each(&card, [](auto* device, void* context) {
|
||||
auto* driver = device_get_driver(device);
|
||||
if (driver == nullptr) return true;
|
||||
if (!driver_is_compatible(driver, "espressif,esp32-sdspi") &&
|
||||
!driver_is_compatible(driver, "espressif,esp32-sdmmc")) return true;
|
||||
auto** out = static_cast<sdmmc_card_t**>(context);
|
||||
*out = esp32_sdcard_get_card(device);
|
||||
return *out == nullptr;
|
||||
});
|
||||
|
||||
#if SOC_SDMMC_HOST_SUPPORTED
|
||||
// Find ESP32 SDMMC device:
|
||||
if (sdcard == nullptr) {
|
||||
device_for_each(&sdcard, [](auto* device, void* context) {
|
||||
if (device_is_ready(device) && device_is_compatible(device, "espressif,esp32-sdmmc")) {
|
||||
auto** sdcard = static_cast<sdmmc_card_t**>(context);
|
||||
auto* sdmmc_card = esp32_sdmmc_get_card(device);
|
||||
if (sdmmc_card) {
|
||||
*sdcard = sdmmc_card;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sdcard == nullptr) {
|
||||
if (card == nullptr) {
|
||||
LOGGER.warn("Couldn't find a mounted SD card");
|
||||
}
|
||||
|
||||
return sdcard;
|
||||
return card;
|
||||
}
|
||||
|
||||
static bool canStartNewMode() {
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
|
||||
#include <Tactility/Logger.h>
|
||||
#include <Tactility/Mutex.h>
|
||||
#include <Tactility/Paths.h>
|
||||
#include <Tactility/Timer.h>
|
||||
#include <Tactility/hal/power/PowerDevice.h>
|
||||
#include <Tactility/hal/sdcard/SdCardDevice.h>
|
||||
#include <tactility/filesystem/file_system.h>
|
||||
#include <Tactility/lvgl/Lvgl.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/service/ServiceContext.h>
|
||||
@@ -239,11 +238,21 @@ class StatusbarService final : public Service {
|
||||
}
|
||||
|
||||
void updateSdCardIcon() {
|
||||
auto* sdcard_fs = findSdcardFileSystem(false);
|
||||
// TODO: Support multiple SD cards
|
||||
if (sdcard_fs != nullptr) {
|
||||
auto mounted = file_system_is_mounted(sdcard_fs);
|
||||
auto* desired_icon = getSdCardStatusIcon(mounted);
|
||||
struct SdCardState { bool found; bool mounted; };
|
||||
SdCardState state = { false, false };
|
||||
|
||||
file_system_for_each(&state, [](FileSystem* fs, void* context) {
|
||||
auto* s = static_cast<SdCardState*>(context);
|
||||
char path[64];
|
||||
if (file_system_get_path(fs, path, sizeof(path)) != ERROR_NONE) return true;
|
||||
if (strncmp(path, "/sdcard", 7) != 0) return true;
|
||||
s->found = true;
|
||||
s->mounted = file_system_is_mounted(fs);
|
||||
return false;
|
||||
});
|
||||
|
||||
if (state.found) {
|
||||
auto* desired_icon = getSdCardStatusIcon(state.mounted);
|
||||
if (sdcard_last_icon != desired_icon) {
|
||||
lvgl::statusbar_icon_set_image(sdcard_icon_id, desired_icon);
|
||||
lvgl::statusbar_icon_set_visibility(sdcard_icon_id, true);
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include <Tactility/app/AppRegistration.h>
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
#include <Tactility/app/App.h>
|
||||
#include <Tactility/hal/sdcard/SdCardDevice.h>
|
||||
#include <Tactility/service/wifi/Wifi.h>
|
||||
#include <esp_wifi_default.h>
|
||||
#include <Tactility/network/HttpdReq.h>
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include <Tactility/Paths.h>
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <Tactility/hal/sdcard/SdCardDevice.h>
|
||||
#include <dirent.h>
|
||||
#include <format>
|
||||
#include <map>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include <Tactility/MountPoints.h>
|
||||
#include <Tactility/file/File.h>
|
||||
#include <Tactility/file/PropertiesFile.h>
|
||||
#include <Tactility/hal/sdcard/SdCardDevice.h>
|
||||
#include <Tactility/Logger.h>
|
||||
#include <Tactility/settings/BootSettings.h>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user