mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-23 00:45:05 +00:00
Compare commits
No commits in common. "75be23eca28a27f0283c0dd7f9d1ddd746fb0d92" and "470e65e90f8744839aad99e23207a2e280f84ced" have entirely different histories.
75be23eca2
...
470e65e90f
@ -13,6 +13,7 @@
|
|||||||
- Mutex: Implement give/take from ISR support (works only for non-recursive ones)
|
- Mutex: Implement give/take from ISR support (works only for non-recursive ones)
|
||||||
- Extend unPhone power driver: add charging status, usb connection status, etc.
|
- Extend unPhone power driver: add charging status, usb connection status, etc.
|
||||||
- Expose app::Paths to TactilityC
|
- Expose app::Paths to TactilityC
|
||||||
|
- Make a ledger for setting CPU affinity of various services and tasks
|
||||||
- CrashHandler: use "corrupted" flag
|
- CrashHandler: use "corrupted" flag
|
||||||
- CrashHandler: process other types of crashes (WDT?)
|
- CrashHandler: process other types of crashes (WDT?)
|
||||||
- Call tt::lvgl::isSyncSet after HAL init and show an error (and crash?) when it is not set.
|
- Call tt::lvgl::isSyncSet after HAL init and show an error (and crash?) when it is not set.
|
||||||
|
|||||||
@ -11,7 +11,6 @@
|
|||||||
#include <Tactility/kernel/SystemEvents.h>
|
#include <Tactility/kernel/SystemEvents.h>
|
||||||
|
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
#include <Tactility/CpuAffinity.h>
|
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
#include "Tactility/app/crashdiagnostics/CrashDiagnostics.h"
|
#include "Tactility/app/crashdiagnostics/CrashDiagnostics.h"
|
||||||
@ -25,25 +24,26 @@
|
|||||||
|
|
||||||
namespace tt::app::boot {
|
namespace tt::app::boot {
|
||||||
|
|
||||||
static std::shared_ptr<hal::display::DisplayDevice> getHalDisplay() {
|
static std::shared_ptr<tt::hal::display::DisplayDevice> getHalDisplay() {
|
||||||
return hal::findFirstDevice<hal::display::DisplayDevice>(hal::Device::Type::Display);
|
return hal::findFirstDevice<hal::display::DisplayDevice>(hal::Device::Type::Display);
|
||||||
}
|
}
|
||||||
|
|
||||||
class BootApp : public App {
|
class BootApp : public App {
|
||||||
|
|
||||||
Thread thread = Thread(
|
private:
|
||||||
"boot",
|
|
||||||
4096,
|
|
||||||
[] { return bootThreadCallback(); },
|
|
||||||
getCpuAffinityConfiguration().system
|
|
||||||
);
|
|
||||||
|
|
||||||
static void setupDisplay() {
|
Thread thread = Thread("boot", 4096, [this]() { return bootThreadCallback(); });
|
||||||
const auto hal_display = getHalDisplay();
|
|
||||||
|
int32_t bootThreadCallback() {
|
||||||
|
TickType_t start_time = kernel::getTicks();
|
||||||
|
|
||||||
|
kernel::publishSystemEvent(kernel::SystemEvent::BootSplash);
|
||||||
|
|
||||||
|
auto hal_display = getHalDisplay();
|
||||||
assert(hal_display != nullptr);
|
assert(hal_display != nullptr);
|
||||||
if (hal_display->supportsBacklightDuty()) {
|
if (hal_display->supportsBacklightDuty()) {
|
||||||
uint8_t backlight_duty = 200;
|
uint8_t backlight_duty = 200;
|
||||||
display::getBacklightDuty(backlight_duty);
|
app::display::getBacklightDuty(backlight_duty);
|
||||||
TT_LOG_I(TAG, "backlight %du", backlight_duty);
|
TT_LOG_I(TAG, "backlight %du", backlight_duty);
|
||||||
hal_display->setBacklightDuty(backlight_duty);
|
hal_display->setBacklightDuty(backlight_duty);
|
||||||
} else {
|
} else {
|
||||||
@ -52,45 +52,27 @@ class BootApp : public App {
|
|||||||
|
|
||||||
if (hal_display->getGammaCurveCount() > 0) {
|
if (hal_display->getGammaCurveCount() > 0) {
|
||||||
uint8_t gamma_curve;
|
uint8_t gamma_curve;
|
||||||
if (display::getGammaCurve(gamma_curve)) {
|
if (app::display::getGammaCurve(gamma_curve)) {
|
||||||
hal_display->setGammaCurve(gamma_curve);
|
hal_display->setGammaCurve(gamma_curve);
|
||||||
TT_LOG_I(TAG, "gamma %du", gamma_curve);
|
TT_LOG_I(TAG, "gamma %du", gamma_curve);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static bool setupUsbBootMode() {
|
|
||||||
if (!hal::usb::isUsbBootMode()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (hal::usb::isUsbBootMode()) {
|
||||||
TT_LOG_I(TAG, "Rebooting into mass storage device mode");
|
TT_LOG_I(TAG, "Rebooting into mass storage device mode");
|
||||||
hal::usb::resetUsbBootMode();
|
hal::usb::resetUsbBootMode();
|
||||||
hal::usb::startMassStorageWithSdmmc();
|
hal::usb::startMassStorageWithSdmmc();
|
||||||
|
} else {
|
||||||
|
initFromBootApp();
|
||||||
|
|
||||||
return true;
|
TickType_t end_time = tt::kernel::getTicks();
|
||||||
}
|
TickType_t ticks_passed = end_time - start_time;
|
||||||
|
TickType_t minimum_ticks = (CONFIG_TT_SPLASH_DURATION / portTICK_PERIOD_MS);
|
||||||
static void waitForMinimalSplashDuration(TickType_t startTime) {
|
|
||||||
const auto end_time = kernel::getTicks();
|
|
||||||
const auto ticks_passed = end_time - startTime;
|
|
||||||
constexpr auto minimum_ticks = (CONFIG_TT_SPLASH_DURATION / portTICK_PERIOD_MS);
|
|
||||||
if (minimum_ticks > ticks_passed) {
|
if (minimum_ticks > ticks_passed) {
|
||||||
kernel::delayTicks(minimum_ticks - ticks_passed);
|
kernel::delayTicks(minimum_ticks - ticks_passed);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t bootThreadCallback() {
|
tt::service::loader::stopApp();
|
||||||
const auto start_time = kernel::getTicks();
|
|
||||||
|
|
||||||
kernel::publishSystemEvent(kernel::SystemEvent::BootSplash);
|
|
||||||
|
|
||||||
setupDisplay();
|
|
||||||
|
|
||||||
if (!setupUsbBootMode()) {
|
|
||||||
initFromBootApp();
|
|
||||||
waitForMinimalSplashDuration(start_time);
|
|
||||||
service::loader::stopApp();
|
|
||||||
startNextApp();
|
startNextApp();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,15 +81,16 @@ class BootApp : public App {
|
|||||||
|
|
||||||
static void startNextApp() {
|
static void startNextApp() {
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
if (esp_reset_reason() == ESP_RST_PANIC) {
|
esp_reset_reason_t reason = esp_reset_reason();
|
||||||
crashdiagnostics::start();
|
if (reason == ESP_RST_PANIC) {
|
||||||
|
app::crashdiagnostics::start();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const auto* config = getConfiguration();
|
auto* config = tt::getConfiguration();
|
||||||
assert(!config->launcherAppId.empty());
|
assert(!config->launcherAppId.empty());
|
||||||
service::loader::startApp(config->launcherAppId);
|
tt::service::loader::startApp(config->launcherAppId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -116,9 +99,9 @@ public:
|
|||||||
auto* image = lv_image_create(parent);
|
auto* image = lv_image_create(parent);
|
||||||
lv_obj_set_size(image, LV_PCT(100), LV_PCT(100));
|
lv_obj_set_size(image, LV_PCT(100), LV_PCT(100));
|
||||||
|
|
||||||
const auto paths = app.getPaths();
|
auto paths = app.getPaths();
|
||||||
const char* logo = hal::usb::isUsbBootMode() ? "logo_usb.png" : "logo.png";
|
const char* logo = hal::usb::isUsbBootMode() ? "logo_usb.png" : "logo.png";
|
||||||
const auto logo_path = paths->getSystemPathLvgl(logo);
|
auto logo_path = paths->getSystemPathLvgl(logo);
|
||||||
TT_LOG_I(TAG, "%s", logo_path.c_str());
|
TT_LOG_I(TAG, "%s", logo_path.c_str());
|
||||||
lv_image_set_src(image, logo_path.c_str());
|
lv_image_set_src(image, logo_path.c_str());
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,8 @@ extern const AppManifest manifest;
|
|||||||
|
|
||||||
class I2cScannerApp : public App {
|
class I2cScannerApp : public App {
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
||||||
std::unique_ptr<Timer> scanTimer = nullptr;
|
std::unique_ptr<Timer> scanTimer = nullptr;
|
||||||
@ -284,7 +286,7 @@ void I2cScannerApp::startScanning() {
|
|||||||
lv_obj_clean(scanListWidget);
|
lv_obj_clean(scanListWidget);
|
||||||
|
|
||||||
scanState = ScanStateScanning;
|
scanState = ScanStateScanning;
|
||||||
scanTimer = std::make_unique<Timer>(Timer::Type::Once, []{
|
scanTimer = std::make_unique<Timer>(Timer::Type::Once, [](){
|
||||||
onScanTimerCallback();
|
onScanTimerCallback();
|
||||||
});
|
});
|
||||||
scanTimer->start(10);
|
scanTimer->start(10);
|
||||||
|
|||||||
@ -2,23 +2,23 @@
|
|||||||
|
|
||||||
#include <Tactility/lvgl/LvglSync.h>
|
#include <Tactility/lvgl/LvglSync.h>
|
||||||
#include <esp_lvgl_port.h>
|
#include <esp_lvgl_port.h>
|
||||||
#include <Tactility/CpuAffinity.h>
|
|
||||||
#include <Tactility/Mutex.h>
|
#include <Tactility/Mutex.h>
|
||||||
|
|
||||||
// LVGL
|
// LVGL
|
||||||
// The minimum task stack seems to be about 3500, but that crashes the wifi app in some scenarios
|
// The minimum task stack seems to be about 3500, but that crashes the wifi app in some scenarios
|
||||||
// At 8192, it sometimes crashes when wifi-auto enables and is busy connecting and then you open WifiManage
|
// At 8192, it sometimes crashes when wifi-auto enables and is busy connecting and then you open WifiManage
|
||||||
#define TDECK_LVGL_TASK_STACK_DEPTH 9216
|
#define TDECK_LVGL_TASK_STACK_DEPTH 9216
|
||||||
auto constexpr TAG = "lvgl";
|
#define TAG "lvgl"
|
||||||
|
|
||||||
namespace tt::lvgl {
|
namespace tt::lvgl {
|
||||||
|
|
||||||
bool initEspLvglPort() {
|
bool initEspLvglPort() {
|
||||||
TT_LOG_D(TAG, "Port init");
|
TT_LOG_D(TAG, "Port init");
|
||||||
|
static lv_disp_t* display = nullptr;
|
||||||
const lvgl_port_cfg_t lvgl_cfg = {
|
const lvgl_port_cfg_t lvgl_cfg = {
|
||||||
.task_priority = static_cast<UBaseType_t>(Thread::Priority::Critical),
|
.task_priority = static_cast<UBaseType_t>(Thread::Priority::Critical),
|
||||||
.task_stack = TDECK_LVGL_TASK_STACK_DEPTH,
|
.task_stack = TDECK_LVGL_TASK_STACK_DEPTH,
|
||||||
.task_affinity = getCpuAffinityConfiguration().graphics,
|
.task_affinity = 1, // -1 = disabled, 0 = core 1, 1 = core 2
|
||||||
.task_max_sleep_ms = 500,
|
.task_max_sleep_ms = 500,
|
||||||
.timer_period_ms = 5
|
.timer_period_ms = 5
|
||||||
};
|
};
|
||||||
@ -28,7 +28,7 @@ bool initEspLvglPort() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
syncSet(&lvgl_port_lock, &lvgl_port_unlock);
|
tt::lvgl::syncSet(&lvgl_port_lock, &lvgl_port_unlock);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
|
#include <Tactility/Tactility.h>
|
||||||
#include <Tactility/TactilityHeadless.h>
|
#include <Tactility/TactilityHeadless.h>
|
||||||
#include <Tactility/lvgl/LvglSync.h>
|
#include <Tactility/lvgl/LvglSync.h>
|
||||||
#include <Tactility/service/ServiceRegistry.h>
|
#include <Tactility/service/ServiceRegistry.h>
|
||||||
|
|||||||
@ -11,7 +11,6 @@
|
|||||||
#include <Tactility/TactilityCore.h>
|
#include <Tactility/TactilityCore.h>
|
||||||
|
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <Tactility/CpuAffinity.h>
|
|
||||||
|
|
||||||
namespace tt::service::screenshot {
|
namespace tt::service::screenshot {
|
||||||
|
|
||||||
@ -110,11 +109,10 @@ void ScreenshotTask::taskStart() {
|
|||||||
thread = new Thread(
|
thread = new Thread(
|
||||||
"screenshot",
|
"screenshot",
|
||||||
8192,
|
8192,
|
||||||
[this] {
|
[this]() {
|
||||||
this->taskMain();
|
this->taskMain();
|
||||||
return 0;
|
return 0;
|
||||||
},
|
}
|
||||||
getCpuAffinityConfiguration().graphics
|
|
||||||
);
|
);
|
||||||
thread->start();
|
thread->start();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "RtosCompat.h"
|
|
||||||
|
|
||||||
namespace tt {
|
|
||||||
|
|
||||||
typedef portBASE_TYPE CpuAffinity;
|
|
||||||
|
|
||||||
constexpr static CpuAffinity None = -1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines the preferred affinity for certain (sub)systems.
|
|
||||||
*/
|
|
||||||
struct CpuAffinityConfiguration {
|
|
||||||
CpuAffinity system;
|
|
||||||
CpuAffinity graphics; // Display, LVGL
|
|
||||||
CpuAffinity wifi;
|
|
||||||
CpuAffinity mainDispatcher;
|
|
||||||
CpuAffinity apps;
|
|
||||||
CpuAffinity timer; // Tactility Timer (based on FreeRTOS)
|
|
||||||
};
|
|
||||||
|
|
||||||
void setCpuAffinityConfiguration(const CpuAffinityConfiguration& config);
|
|
||||||
|
|
||||||
const CpuAffinityConfiguration& getCpuAffinityConfiguration();
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -18,7 +18,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
struct TimerHandleDeleter {
|
struct TimerHandleDeleter {
|
||||||
void operator()(TimerHandle_t handleToDelete) const {
|
void operator()(TimerHandle_t handleToDelete) {
|
||||||
xTimerDelete(handleToDelete, portMAX_DELAY);
|
xTimerDelete(handleToDelete, portMAX_DELAY);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,85 +0,0 @@
|
|||||||
#include "Tactility/CpuAffinity.h"
|
|
||||||
|
|
||||||
#include <Tactility/Check.h>
|
|
||||||
|
|
||||||
namespace tt {
|
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
|
|
||||||
static CpuAffinity getEspWifiAffinity() {
|
|
||||||
#ifdef CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0
|
|
||||||
return 0;
|
|
||||||
#elif defined(CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1)
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warning: Must watch ESP WiFi, as this task is used by WiFi
|
|
||||||
static CpuAffinity getEspMainSchedulerAffinity() {
|
|
||||||
#ifdef CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0
|
|
||||||
return 0;
|
|
||||||
#elif defined(CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1)
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static CpuAffinity getFreeRtosTimerAffinity() {
|
|
||||||
#if defined(CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY)
|
|
||||||
return None;
|
|
||||||
#elif defined(CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU0)
|
|
||||||
return 0;
|
|
||||||
#elif defined(CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU1)
|
|
||||||
return 1;
|
|
||||||
#else
|
|
||||||
static_assert(false);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CONFIG_FREERTOS_NUMBER_OF_CORES == 1
|
|
||||||
static const CpuAffinityConfiguration esp = {
|
|
||||||
.system = 0,
|
|
||||||
.graphics = 0,
|
|
||||||
.wifi = 0,
|
|
||||||
.mainDispatcher = 0,
|
|
||||||
.apps = 0,
|
|
||||||
.timer = getFreeRtosTimerAffinity()
|
|
||||||
};
|
|
||||||
#elif CONFIG_FREERTOS_NUMBER_OF_CORES == 2
|
|
||||||
static const CpuAffinityConfiguration esp = {
|
|
||||||
.system = 0,
|
|
||||||
.graphics = 1,
|
|
||||||
.wifi = getEspWifiAffinity(),
|
|
||||||
.mainDispatcher = getEspMainSchedulerAffinity(),
|
|
||||||
.apps = 1,
|
|
||||||
.timer = getFreeRtosTimerAffinity()
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
static const CpuAffinityConfiguration simulator = {
|
|
||||||
.system = None,
|
|
||||||
.graphics = None,
|
|
||||||
.wifi = None,
|
|
||||||
.mainDispatcher = 0,
|
|
||||||
.apps = None,
|
|
||||||
.timer = None
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const CpuAffinityConfiguration& getCpuAffinityConfiguration() {
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
|
|
||||||
#if CONFIG_FREERTOS_NUMBER_OF_CORES == 2
|
|
||||||
// WiFi uses the main dispatcher to defer operations in the background
|
|
||||||
assert(esp.wifi == esp.mainDispatcher);
|
|
||||||
#endif // CORES
|
|
||||||
return esp;
|
|
||||||
|
|
||||||
#else
|
|
||||||
return simulator;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -13,7 +13,7 @@ void Timer::onCallback(TimerHandle_t hTimer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static TimerHandle_t createTimer(Timer::Type type, void* timerId, TimerCallbackFunction_t callback) {
|
static inline TimerHandle_t createTimer(Timer::Type type, void* timerId, TimerCallbackFunction_t callback) {
|
||||||
assert(timerId != nullptr);
|
assert(timerId != nullptr);
|
||||||
assert(callback != nullptr);
|
assert(callback != nullptr);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user