Filesystem improvements and more (#148)

- Rename `assets` and `config` partitions to `system` and `data`
- Change partition type from `spiffs` to `fat`, so we can have sub-directories
- Fix crash when doing WiFi scan: Increased system event task size to 3kB. 
- Free up IRAM on ESP32 (it was required for the Core2, but I also freed up the same amount for Yellow Board)
- Introduced `Paths` objects that can be retrieved by `AppContext` and `ServiceContext`. Apps and services now have their own relative paths. Assets were re-arranged into the correct paths.
- Rename simulator window title to "Tactility"
- Refactored statusbar widget so it persists icon paths properly (it kept a const char* reference, but didn't copy it, so it crashed when the related std::string was destroyed)
- Created `Partitions.h` to expose some useful variables
- Moved USB config in various `sdkconfig`  (it was part of the "default" section, but it shouldn't be)
- Updated domain name
This commit is contained in:
Ken Van Hoeylandt
2025-01-05 20:44:33 +01:00
committed by GitHub
parent 7187e5e49e
commit ff4287e2ce
107 changed files with 592 additions and 259 deletions
+1 -34
View File
@@ -1,12 +1,8 @@
#pragma once
#define TT_ASSET_FOLDER "A:/assets/"
#define TT_ASSET_FOLDER "A:/system/"
#define TT_ASSET(file) TT_ASSET_FOLDER file
// Splash
#define TT_ASSETS_BOOT_LOGO TT_ASSET("boot_logo.png")
#define TT_ASSETS_BOOT_LOGO_USB TT_ASSET("boot_logo_usb.png")
// UI
#define TT_ASSETS_UI_SPINNER TT_ASSET("spinner.png")
@@ -18,32 +14,3 @@
#define TT_ASSETS_APP_ICON_I2C_SETTINGS TT_ASSET("app_icon_i2c.png")
#define TT_ASSETS_APP_ICON_SETTINGS TT_ASSET("app_icon_settings.png")
#define TT_ASSETS_APP_ICON_SYSTEM_INFO TT_ASSET("app_icon_system_info.png")
// SD card status
#define TT_ASSETS_ICON_SDCARD TT_ASSET("sdcard.png")
#define TT_ASSETS_ICON_SDCARD_ALERT TT_ASSET("sdcard_alert.png")
// Wifi status
#define TT_ASSETS_ICON_WIFI_OFF_WHITE TT_ASSET("wifi_off_white.png")
#define TT_ASSETS_ICON_WIFI_SCAN_WHITE TT_ASSET("wifi_scan_white.png")
#define TT_ASSETS_ICON_WIFI_SIGNAL_WEAK_WHITE TT_ASSET("wifi_signal_weak_white.png")
#define TT_ASSETS_ICON_WIFI_SIGNAL_MEDIUM_WHITE TT_ASSET("wifi_signal_medium_white.png")
#define TT_ASSETS_ICON_WIFI_SIGNAL_STRONG_WHITE TT_ASSET("wifi_signal_strong_white.png")
// Black (Wifi Manage)
#define TT_ASSETS_ICON_WIFI_LOCK_BLACK TT_ASSET("wifi_lock_black.png")
#define TT_ASSETS_ICON_WIFI_SIGNAL_WEAK_BLACK TT_ASSET("wifi_signal_weak_black.png")
#define TT_ASSETS_ICON_WIFI_SIGNAL_MEDIUM_BLACK TT_ASSET("wifi_signal_medium_black.png")
#define TT_ASSETS_ICON_WIFI_SIGNAL_STRONG_BLACK TT_ASSET("wifi_signal_strong_black.png")
// Power status
#define TT_ASSETS_ICON_POWER_0 TT_ASSET("power_0.png")
#define TT_ASSETS_ICON_POWER_10 TT_ASSET("power_10.png")
#define TT_ASSETS_ICON_POWER_20 TT_ASSET("power_20.png")
#define TT_ASSETS_ICON_POWER_30 TT_ASSET("power_30.png")
#define TT_ASSETS_ICON_POWER_40 TT_ASSET("power_40.png")
#define TT_ASSETS_ICON_POWER_50 TT_ASSET("power_50.png")
#define TT_ASSETS_ICON_POWER_60 TT_ASSET("power_60.png")
#define TT_ASSETS_ICON_POWER_70 TT_ASSET("power_70.png")
#define TT_ASSETS_ICON_POWER_80 TT_ASSET("power_80.png")
#define TT_ASSETS_ICON_POWER_90 TT_ASSET("power_90.png")
#define TT_ASSETS_ICON_POWER_100 TT_ASSET("power_100.png")
@@ -1,76 +0,0 @@
#ifdef ESP_TARGET
#include "EspPartitions.h"
#include "EspPartitions_i.h"
#include "Log.h"
#include "esp_spiffs.h"
#include "nvs_flash.h"
namespace tt {
static const char* TAG = "filesystem";
static esp_err_t initNvsFlashSafely() {
esp_err_t result = nvs_flash_init();
if (result == ESP_ERR_NVS_NO_FREE_PAGES || result == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
result = nvs_flash_init();
}
return result;
}
static esp_err_t initSpiffs(esp_vfs_spiffs_conf_t* conf) {
esp_err_t ret = esp_vfs_spiffs_register(conf);
if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
TT_LOG_E(TAG, "Failed to mount or format filesystem %s", conf->base_path);
} else if (ret == ESP_ERR_NOT_FOUND) {
TT_LOG_E(TAG, "Failed to find SPIFFS partition %s", conf->base_path);
} else {
TT_LOG_E(TAG, "Failed to initialize SPIFFS %s (%s)", conf->base_path, esp_err_to_name(ret));
}
return ESP_FAIL;
}
size_t total = -1, used = 0;
ret = esp_spiffs_info(NULL, &total, &used);
if (ret != ESP_OK) {
TT_LOG_E(TAG, "Failed to get SPIFFS partition information for %s (%s)", conf->base_path, esp_err_to_name(ret));
} else {
TT_LOG_I(TAG, "Partition size for %s: total: %d, used: %d", conf->base_path, total, used);
}
return ESP_OK;
}
esp_err_t initEspPartitions() {
ESP_ERROR_CHECK(initNvsFlashSafely());
esp_vfs_spiffs_conf_t assets_spiffs = {
.base_path = MOUNT_POINT_ASSETS,
.partition_label = NULL,
.max_files = 100,
.format_if_mount_failed = false
};
if (initSpiffs(&assets_spiffs) != ESP_OK) {
return ESP_FAIL;
}
esp_vfs_spiffs_conf_t config_spiffs = {
.base_path = MOUNT_POINT_CONFIG,
.partition_label = "config",
.max_files = 100,
.format_if_mount_failed = false
};
if (initSpiffs(&config_spiffs) != ESP_OK) {
return ESP_FAIL;
}
return ESP_OK;
}
} // namespace
#endif // ESP_TARGET
-12
View File
@@ -1,12 +0,0 @@
#pragma once
#ifdef ESP_TARGET
namespace tt {
#define MOUNT_POINT_ASSETS "/assets"
#define MOUNT_POINT_CONFIG "/config"
} // namespace
#endif // ESP_TARGET
+21
View File
@@ -0,0 +1,21 @@
#pragma once
namespace tt {
#define SYSTEM_PARTITION_NAME "system"
#ifdef ESP_PLATFORM
#define MOUNT_POINT_SYSTEM "/system"
#else
#define MOUNT_POINT_SYSTEM "system"
#endif
#define DATA_PARTITION_NAME "data"
#ifdef ESP_PLATFORM
#define MOUNT_POINT_DATA "/data"
#else
#define MOUNT_POINT_DATA "data"
#endif
} // namespace
@@ -0,0 +1,54 @@
#ifdef ESP_TARGET
#include "EspPartitions_i.h"
#include "Log.h"
#include <esp_vfs_fat.h>
#include <nvs_flash.h>
namespace tt {
static const char* TAG = "partitions";
static esp_err_t initNvsFlashSafely() {
esp_err_t result = nvs_flash_init();
if (result == ESP_ERR_NVS_NO_FREE_PAGES || result == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
result = nvs_flash_init();
}
return result;
}
static wl_handle_t data_wl_handle = WL_INVALID_HANDLE;
esp_err_t initPartitionsEsp() {
ESP_ERROR_CHECK(initNvsFlashSafely());
const esp_vfs_fat_mount_config_t mount_config = {
.format_if_mount_failed = false,
.max_files = 4,
.allocation_unit_size = CONFIG_WL_SECTOR_SIZE,
.disk_status_check_enable = false,
.use_one_fat = true,
};
auto system_result = esp_vfs_fat_spiflash_mount_ro("/system", "system", &mount_config);
if (system_result != ESP_OK) {
TT_LOG_E(TAG, "Failed to mount /system (%s)", esp_err_to_name(system_result));
} else {
TT_LOG_I(TAG, "Mounted /system");
}
auto data_result = esp_vfs_fat_spiflash_mount_rw_wl("/data", "data", &mount_config, &data_wl_handle);
if (data_result != ESP_OK) {
TT_LOG_E(TAG, "Failed to mount /data (%s)", esp_err_to_name(data_result));
} else {
TT_LOG_I(TAG, "Mounted /data");
}
return system_result == ESP_OK && data_result == ESP_OK;
}
} // namespace
#endif // ESP_TARGET
@@ -1,7 +1,5 @@
#include "TactilityCore.h"
#ifdef ESP_TARGET
#include "TactilityCore.h"
#include "EspPartitions_i.h"
#include "esp_event.h"
@@ -13,7 +11,7 @@ namespace tt {
#define TAG "tactility"
// Initialize NVS
static void initEspNvs() {
static void initNvs() {
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
TT_LOG_I(TAG, "nvs erasing");
@@ -24,15 +22,15 @@ static void initEspNvs() {
TT_LOG_I(TAG, "nvs initialized");
}
static void initEspNetwork() {
static void initNetwork() {
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
}
void initEsp() {
initEspNvs();
initEspPartitions();
initEspNetwork();
initNvs();
initPartitionsEsp();
initNetwork();
}
} // namespace
+1 -1
View File
@@ -19,7 +19,7 @@ void init(const Configuration& configuration) {
if (configuration.sdcard != nullptr) {
TT_LOG_I(TAG, "Mounting sdcard");
if (!configuration.sdcard->mount(TT_SDCARD_MOUNT_POINT )) {
if (!configuration.sdcard->mount(TT_SDCARD_MOUNT_POINT)) {
TT_LOG_W(TAG, "SD card mount failed (init can continue)");
}
}
+1
View File
@@ -4,6 +4,7 @@
namespace tt::hal {
#define TT_SDCARD_MOUNT_NAME "sdcard"
#define TT_SDCARD_MOUNT_POINT "/sdcard"
class SdCard {
@@ -6,6 +6,8 @@
namespace tt::service {
class Paths;
class ServiceContext {
protected:
@@ -17,6 +19,68 @@ public:
virtual const service::ServiceManifest& getManifest() const = 0;
virtual std::shared_ptr<void> getData() const = 0;
virtual void setData(std::shared_ptr<void> newData) = 0;
virtual std::unique_ptr<Paths> getPaths() const = 0;
};
class Paths {
public:
Paths() = default;
virtual ~Paths() = default;
/**
* Returns the directory path for the data location for a service.
* The data directory is intended to survive OS upgrades.
* The path will not end with a "/".
*/
virtual std::string getDataDirectory() const = 0;
/**
* @see getDataDirectory(), but with LVGL prefix.
*/
virtual std::string getDataDirectoryLvgl() const = 0;
/**
* Returns the full path for an entry inside the data location for a service.
* The data directory is intended to survive OS upgrades.
* Configuration data should be stored here.
* @param[in] childPath the path without a "/" prefix
*/
virtual std::string getDataPath(const std::string& childPath) const = 0;
/**
* @see getDataPath(), but with LVGL prefix.
*/
virtual std::string getDataPathLvgl(const std::string& childPath) const = 0;
/**
* Returns the directory path for the system location for a service.
* The system directory is not intended to survive OS upgrades.
* You should not store configuration data here.
* The path will not end with a "/".
* This is mainly used for core services.
*/
virtual std::string getSystemDirectory() const = 0;
/**
* @see getSystemDirectory(), but with LVGL prefix.
*/
virtual std::string getSystemDirectoryLvgl() const = 0;
/**
* Returns the full path for an entry inside the system location for an app.
* The data directory is not intended to survive OS upgrades.
* You should not store configuration data here.
* This is mainly used for core apps (system/boot/settings type).
* @param[in] childPath the path without a "/" prefix
*/
virtual std::string getSystemPath(const std::string& childPath) const = 0;
/**
* @see getSystemPath(), but with LVGL prefix.
*/
virtual std::string getSystemPathLvgl(const std::string& childPath) const = 0;
};
} // namespace
@@ -1,6 +1,7 @@
#include <utility>
#include "service/ServiceInstance.h"
#include "service/ServiceInstancePaths.h"
namespace tt::service {
@@ -21,4 +22,8 @@ void ServiceInstance::setData(std::shared_ptr<void> newData) {
mutex.release();
}
std::unique_ptr<Paths> ServiceInstance::getPaths() const {
return std::make_unique<ServiceInstancePaths>(manifest);
}
}
@@ -0,0 +1,48 @@
#include "service/ServiceInstancePaths.h"
#include "Partitions.h"
#define LVGL_PATH_PREFIX std::string("A:/")
#ifdef ESP_PLATFORM
#define PARTITION_PREFIX std::string("/")
#else
#define PARTITION_PREFIX std::string("")
#endif
namespace tt::service {
std::string ServiceInstancePaths::getDataDirectory() const {
return PARTITION_PREFIX + DATA_PARTITION_NAME + "/service/" + manifest.id;
}
std::string ServiceInstancePaths::getDataDirectoryLvgl() const {
return LVGL_PATH_PREFIX + DATA_PARTITION_NAME + "/service/" + manifest.id;
}
std::string ServiceInstancePaths::getDataPath(const std::string& childPath) const {
assert(!childPath.starts_with('/'));
return PARTITION_PREFIX + DATA_PARTITION_NAME + "/service/" + manifest.id + '/' + childPath;
}
std::string ServiceInstancePaths::getDataPathLvgl(const std::string& childPath) const {
assert(!childPath.starts_with('/'));
return LVGL_PATH_PREFIX + DATA_PARTITION_NAME + "/service/" + manifest.id + '/' + childPath;
}
std::string ServiceInstancePaths::getSystemDirectory() const {
return PARTITION_PREFIX + SYSTEM_PARTITION_NAME + "/service/" + manifest.id;
}
std::string ServiceInstancePaths::getSystemDirectoryLvgl() const {
return LVGL_PATH_PREFIX + SYSTEM_PARTITION_NAME + "/service/" + manifest.id;
}
std::string ServiceInstancePaths::getSystemPath(const std::string& childPath) const {
assert(!childPath.starts_with('/'));
return PARTITION_PREFIX + SYSTEM_PARTITION_NAME + "/service/" + manifest.id + '/' + childPath;
}
std::string ServiceInstancePaths::getSystemPathLvgl(const std::string& childPath) const {
return LVGL_PATH_PREFIX + SYSTEM_PARTITION_NAME + "/service/" + manifest.id + '/' + childPath;
}
}