Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion inc/sp140/system_monitors.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@
void addInternalMonitors();
void addAltimeterMonitors();

// Thread-safe cached CPU temperature reading (updates max once per second)
// Prime the CPU temperature cache during single-threaded setup.
void primeCpuTemperatureCache();

// Refresh the sensor at most once per second. ctrlSensorTask is the sole
// runtime owner; all other tasks must use getCachedCpuTemperature().
float refreshCpuTemperature();

// Cross-core read of the last published CPU temperature; never touches tsens.
float getCachedCpuTemperature();

#endif // INC_SP140_SYSTEM_MONITORS_H_
9 changes: 4 additions & 5 deletions src/sp140/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,10 +310,9 @@ void throttleTask(void *pvParameters) {
}

// Lightweight task: reads controller sensors and writes to TelemetryHub at 10Hz.
// Uses CACHED barometer/CPU values — uiTask is the sole I2C reader, and
// getCachedCpuTemperature throttles tsens access. This avoids i2cMutex
// contention and the "tsens: Do not configure..." error that arises when
// multiple tasks call temperatureRead() concurrently.
// Uses CACHED barometer/CPU values — uiTask is the sole I2C reader, and this
// task is the sole runtime owner of tsens refresh. Other tasks only consume the
// atomically published CPU temperature.
void ctrlSensorTask(void *pvParameters) {
(void)pvParameters;
TickType_t lastWake = xTaskGetTickCount();
Expand All @@ -327,7 +326,7 @@ void ctrlSensorTask(void *pvParameters) {
float bt = getBaroTemperature();
float bp = getBaroPressure();
float vs = getCachedVerticalSpeed();
float mt = getCachedCpuTemperature();
float mt = refreshCpuTemperature();
uint16_t pr = getLastThrottleRaw();
telemetryHubWriteController(alt, bt, bp, vs, mt, pr, now);
vTaskDelayUntil(&lastWake, sensorTicks);
Expand Down
3 changes: 3 additions & 0 deletions src/sp140/simple_monitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,9 @@ void initSimpleMonitor() {
addESCMonitors();
addBMSMonitors();
addAltimeterMonitors();
// Prime while setup is still single-threaded so monitor readers never see
// the zero-initialized cache and no runtime task races tsens initialization.
primeCpuTemperatureCache();
addInternalMonitors();
USBSerial.printf("Monitoring %d sensors\n", monitors.size());
}
Expand Down
21 changes: 16 additions & 5 deletions src/sp140/system_monitors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "sp140/monitor_config.h"
#include "sp140/altimeter.h"
#include <Arduino.h>
#include <atomic>

// External references to core monitoring infrastructure
extern std::vector<IMonitor*> monitors;
Expand All @@ -10,18 +11,28 @@ extern MultiLogger multiLogger;
// External reference to BMP sensor status
extern bool bmpPresent;

// Cached CPU temperature to avoid "tsens: Do not configure the temp sensor when it's running!" error
static float cachedCpuTemp = 0.0f;
// ESP32 tsens configuration is not safe from concurrent tasks. One task owns
// temperatureRead(); readers consume this atomic cross-core publication.
static std::atomic<float> cachedCpuTemp{0.0f};
static unsigned long lastCpuTempRead = 0;
static const unsigned long CPU_TEMP_READ_INTERVAL = 1000; // Read every 1 second

float getCachedCpuTemperature() {
void primeCpuTemperatureCache() {
cachedCpuTemp.store(temperatureRead(), std::memory_order_relaxed);
lastCpuTempRead = millis();
}

float refreshCpuTemperature() {
unsigned long now = millis();
if (now - lastCpuTempRead >= CPU_TEMP_READ_INTERVAL) {
cachedCpuTemp = temperatureRead();
cachedCpuTemp.store(temperatureRead(), std::memory_order_relaxed);
lastCpuTempRead = now;
}
return cachedCpuTemp;
return cachedCpuTemp.load(std::memory_order_relaxed);
}

float getCachedCpuTemperature() {
return cachedCpuTemp.load(std::memory_order_relaxed);
}

void addInternalMonitors() {
Expand Down
Loading