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:
committed by
GitHub
parent
7187e5e49e
commit
ff4287e2ce
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
+6
-8
@@ -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
|
||||
@@ -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)");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user