fix(esp): prevent map SD reads from starving display

This commit is contained in:
liu weikai committed 2026-06-16 23:49:11 +08:00
1 parent 27a7b84082
commit 066e6b9fc8
6 files changed
+86 -15

No files matched your search

@@ -229,6 +229,13 @@ uint8_t current_map_zoom()
std::min(s_map_zoom, ::ui::widgets::map::kMaxZoom)));
}
bool has_valid_viewport_center(const ::ui::map::MapViewport& viewport)
{
return std::isfinite(viewport.center_lat) &&
std::isfinite(viewport.center_lon) &&
(viewport.center_lat != 0.0 || viewport.center_lon != 0.0);
}
void sync_workspace_layers_from_renderer()
{
auto& state = ::ui::presentation_sources::runtime_map_workspace_state();
@@ -244,13 +251,10 @@ void sync_workspace_viewport_from_renderer()
auto& model = map_workspace_model();
auto viewport = model.viewport();
viewport.zoom = current_map_zoom();
if (!std::isfinite(viewport.center_lat) || !std::isfinite(viewport.center_lon) ||
(viewport.center_lat == 0.0 && viewport.center_lon == 0.0))
if (has_valid_viewport_center(viewport))
{
viewport.center_lat = gps_ui::kDefaultLat;
viewport.center_lon = gps_ui::kDefaultLng;
(void)model.setViewport(viewport);
}
(void)model.setViewport(viewport);
(void)model.setActiveTool(::ui::map::MapToolKind::Pan);
}
@@ -300,19 +304,16 @@ bool commit_pending_map_pan_from_screen()
const auto& config = app::configFacade().getConfig();
::ui::widgets::map::Model model{};
const bool has_viewport_center =
std::isfinite(snapshot.viewport.center_lat) &&
std::isfinite(snapshot.viewport.center_lon) &&
(snapshot.viewport.center_lat != 0.0 || snapshot.viewport.center_lon != 0.0);
const bool has_viewport_center = has_valid_viewport_center(snapshot.viewport);
model.focus_point.valid = has_viewport_center || snapshot.self.valid;
model.focus_point.lat = has_viewport_center
? snapshot.viewport.center_lat
: (snapshot.self.valid ? snapshot.self.lat
: gps_ui::kDefaultLat);
: 0.0);
model.focus_point.lon = has_viewport_center
? snapshot.viewport.center_lon
: (snapshot.self.valid ? snapshot.self.lon
: gps_ui::kDefaultLng);
: 0.0);
model.zoom = snapshot.viewport.zoom == 0 ? s_map_zoom : snapshot.viewport.zoom;
model.pan_x = s_map_pan_x;
model.pan_y = s_map_pan_y;
@@ -160,6 +160,22 @@ int main()
assert(snapshot.team.visible_members == 2);
assert(snapshot.team.stale_members == 1);
state.has_viewport = false;
state.last_viewport = {};
gps.snapshot.fix_valid = false;
request.requested_viewport = viewport(0.0, 0.0, 12);
assert(source.buildMapWorkspaceSnapshot(request, snapshot));
assert(snapshot.header.valid);
assert(!snapshot.self.valid);
assert(!snapshot.can_center_on_self);
assert(snapshot.viewport.center_lat == 0.0);
assert(snapshot.viewport.center_lon == 0.0);
assert(snapshot.viewport.zoom == 12);
gps.snapshot.fix_valid = true;
gps.snapshot.latitude = 52.4068;
gps.snapshot.longitude = -1.5197;
const auto center = sink.centerOnSelf();
assert(center.ok);
assert(state.has_viewport);
@@ -207,7 +207,8 @@ constexpr uint32_t kMapTileDiagnosticLogIntervalMs = 1000;
constexpr TickType_t kMapTileWorkerPostCommandYieldTicks = pdMS_TO_TICKS(32);
constexpr uint32_t kMapTileDisplaySpiSlowHoldMs = 8;
constexpr uint32_t kMapTileDisplaySpiNormalCooldownMs = 160;
constexpr uint32_t kMapTileDisplaySpiSlowCooldownMs = 600;
constexpr uint32_t kMapTileDisplaySpiSlowCooldownMs = 1500;
constexpr uint32_t kMapTileDisplayPressureCooldownMs = 1500;
uint32_t g_map_tile_decode_log_ms = 0;
uint32_t g_map_tile_event_log_ms = 0;
@@ -860,6 +861,19 @@ class EspMapTileBusArbiter final : public sys::runtime::IBusArbiter
const sys::runtime::BusAcquireRequest& request) override
{
const uint32_t start_ms = sys::millis_now();
if (::platform::esp::common::display_spi_recently_timed_out(
start_ms,
kMapTileDisplayPressureCooldownMs))
{
sys::runtime::BusAcquireResult result{};
result.status = sys::runtime::BusAcquireStatus::Busy;
result.diagnostics.resource = request.resource;
result.diagnostics.command_id = request.command_id;
result.diagnostics.policy = sys::runtime::BusAccessPolicy::DisplayFrameCritical;
updateHealth(result.status, start_ms);
return result;
}
if (static_cast<int32_t>(cooldown_until_ms_ - start_ms) > 0)
{
sys::runtime::BusAcquireResult result{};
@@ -1844,11 +1858,11 @@ void tileToLatLng(int tile_x, int tile_y, int zoom, double& lat, double& lng)
*/
void get_screen_center_lat_lng(const TileContext& ctx, double& lat, double& lng)
{
lat = 0.0;
lng = 0.0;
if (!ctx.map_container || !ctx.anchor || !ctx.anchor->valid)
{
// If anchor is invalid, return default London coordinates
lat = gps_ui::kDefaultLat;
lng = gps_ui::kDefaultLng;
return;
}
@@ -19,6 +19,7 @@ constexpr uint32_t kDisplayLockTimeoutLogIntervalMs = 1000;
uint32_t s_last_display_lock_timeout_log_ms = 0;
uint32_t s_suppressed_display_lock_timeout_logs = 0;
volatile uint32_t s_last_display_spi_timeout_ms = 0;
bool lock_or_log(LilyGoDispArduinoSPI& spi, TickType_t wait_ticks, const char* op)
{
@@ -28,6 +29,7 @@ bool lock_or_log(LilyGoDispArduinoSPI& spi, TickType_t wait_ticks, const char* o
}
const uint32_t now_ms = millis();
::platform::esp::common::note_display_spi_timeout(now_ms);
++s_suppressed_display_lock_timeout_logs;
if (s_last_display_lock_timeout_log_ms == 0 ||
now_ms - s_last_display_lock_timeout_log_ms >= kDisplayLockTimeoutLogIntervalMs)
@@ -59,6 +61,23 @@ void shared_spi_unlock()
}
}
void note_display_spi_timeout(uint32_t now_ms)
{
s_last_display_spi_timeout_ms = now_ms;
}
uint32_t last_display_spi_timeout_ms()
{
return s_last_display_spi_timeout_ms;
}
bool display_spi_recently_timed_out(uint32_t now_ms, uint32_t window_ms)
{
const uint32_t last_timeout_ms = s_last_display_spi_timeout_ms;
return last_timeout_ms != 0 &&
static_cast<uint32_t>(now_ms - last_timeout_ms) < window_ms;
}
} // namespace platform::esp::common
bool LilyGoDispArduinoSPI::lock(TickType_t xTicksToWait)
@@ -1,6 +1,7 @@
#pragma once
#include "freertos/FreeRTOS.h"
#include <stdint.h>
namespace platform::esp::common
{
@@ -10,6 +11,9 @@ namespace platform::esp::common
// share one controller. It is not display-specific.
bool shared_spi_lock(TickType_t xTicksToWait);
void shared_spi_unlock();
void note_display_spi_timeout(uint32_t now_ms);
uint32_t last_display_spi_timeout_ms();
bool display_spi_recently_timed_out(uint32_t now_ms, uint32_t window_ms);
class SharedSpiLockGuard
{
@@ -11,4 +11,21 @@ bool shared_spi_lock(TickType_t xTicksToWait)
void shared_spi_unlock() {}
void note_display_spi_timeout(uint32_t now_ms)
{
(void)now_ms;
}
uint32_t last_display_spi_timeout_ms()
{
return 0;
}
bool display_spi_recently_timed_out(uint32_t now_ms, uint32_t window_ms)
{
(void)now_ms;
(void)window_ms;
return false;
}
} // namespace platform::esp::common