доработки по интерфейсу
This commit is contained in:
@@ -5,11 +5,22 @@
|
||||
|
||||
#include <driver/gpio.h>
|
||||
#include <esp_cpu.h>
|
||||
#include <esp_task_wdt.h>
|
||||
#include <esp_timer.h>
|
||||
#include <esp32-hal-cpu.h>
|
||||
#include <soc/gpio_struct.h>
|
||||
#include <string.h>
|
||||
|
||||
static inline uint32_t IRAM_ATTR maskAllInterrupts() {
|
||||
uint32_t state;
|
||||
asm volatile("rsil %0, 15" : "=a"(state) :: "memory");
|
||||
return state;
|
||||
}
|
||||
|
||||
static inline void IRAM_ATTR restoreInterrupts(uint32_t state) {
|
||||
asm volatile("wsr %0, ps\nrsync" :: "a"(state) : "memory");
|
||||
}
|
||||
|
||||
void DriverEdgeStats::reset() {
|
||||
memset(this, 0, sizeof(*this));
|
||||
minDelayTicks = minResponseTicks = UINT32_MAX;
|
||||
@@ -78,7 +89,13 @@ bool DriverTest::start(uint32_t frequencyHz, uint32_t pulseNs,
|
||||
faultLongTicks_ = nsToTicks(DRIVER_FAULT_MIN_NS);
|
||||
stuckTicks_ = nsToTicks(DRIVER_RX_STUCK_MIN_NS);
|
||||
testTicks_ = static_cast<uint64_t>(captureHz_) * testTimeMs / 1000ULL;
|
||||
subsampleTicks_ = testTicks_ / SUBSAMPLE_COUNT;
|
||||
const uint32_t requestedSubsamples = testTimeMs < 1000U ?
|
||||
DRIVER_SHORT_SAMPLE_PROGRESS_STEPS :
|
||||
(testTimeMs + DRIVER_PROGRESS_INTERVAL_MS - 1U) /
|
||||
DRIVER_PROGRESS_INTERVAL_MS;
|
||||
subsampleCount_ = static_cast<uint8_t>(
|
||||
requestedSubsamples > UINT8_MAX ? UINT8_MAX : requestedSubsamples);
|
||||
subsampleTicks_ = testTicks_ / subsampleCount_;
|
||||
if (!pollPeriodCycles_ || !pollWindowAfterCycles_ ||
|
||||
!ackStartMaxTicks_ || !faultLongTicks_ || !stuckTicks_ ||
|
||||
!testTicks_ || !subsampleTicks_)
|
||||
@@ -117,14 +134,14 @@ bool DriverTest::start(uint32_t frequencyHz, uint32_t pulseNs,
|
||||
}
|
||||
|
||||
bool DriverTest::armCapture() {
|
||||
Serial.flush();
|
||||
// Never wait for USB/Serial here: a disconnected or slow host must not
|
||||
// delay a subsample or consume the test's global timeout.
|
||||
if (!__atomic_load_n(&core0WdtDisabled_, __ATOMIC_ACQUIRE)) {
|
||||
const bool disabled = disableCore0WDT();
|
||||
TaskHandle_t idle0 = xTaskGetIdleTaskHandleForCore(0);
|
||||
const bool watched = idle0 && esp_task_wdt_status(idle0) == ESP_OK;
|
||||
const bool disabled = watched && disableCore0WDT();
|
||||
__atomic_store_n(&core0WdtDisabled_, disabled, __ATOMIC_RELEASE);
|
||||
if (!disabled) {
|
||||
state_ = DriverState::IDLE;
|
||||
return false;
|
||||
}
|
||||
// If IDLE0 is not watched there is nothing to remove or restore.
|
||||
}
|
||||
__atomic_store_n(&captureReady_, false, __ATOMIC_RELEASE);
|
||||
__atomic_store_n(&captureActive_, true, __ATOMIC_RELEASE);
|
||||
@@ -184,6 +201,8 @@ void IRAM_ATTR DriverTest::pollTaskLoop() {
|
||||
uint8_t hotCount = 0;
|
||||
bool sawTxStart = false;
|
||||
bool critical = false;
|
||||
bool allInterruptsMasked = false;
|
||||
uint32_t interruptState = 0;
|
||||
|
||||
auto sampleOnce = [&]() {
|
||||
const uint32_t current = GPIO.in & PIN_MASK;
|
||||
@@ -218,12 +237,18 @@ void IRAM_ATTR DriverTest::pollTaskLoop() {
|
||||
for (uint8_t i = 0; i < 16U; ++i) sampleOnce();
|
||||
if (sawTxStart) windowEnd = lastTxStart + pollWindowAfterCycles_;
|
||||
const bool synchronized = sawTxStart;
|
||||
if (synchronized) {
|
||||
interruptState = maskAllInterrupts();
|
||||
allInterruptsMasked = true;
|
||||
}
|
||||
|
||||
while (__atomic_load_n(&captureActive_, __ATOMIC_ACQUIRE) && synchronized) {
|
||||
while (__atomic_load_n(&captureActive_, __ATOMIC_ACQUIRE) &&
|
||||
static_cast<int32_t>(esp_cpu_get_cycle_count() - windowEnd) < 0)
|
||||
for (uint8_t i = 0; i < 16U; ++i) sampleOnce();
|
||||
|
||||
restoreInterrupts(interruptState);
|
||||
allInterruptsMasked = false;
|
||||
portEXIT_CRITICAL(&pollMux_);
|
||||
critical = false;
|
||||
flushHot();
|
||||
@@ -249,8 +274,11 @@ void IRAM_ATTR DriverTest::pollTaskLoop() {
|
||||
|
||||
portENTER_CRITICAL(&pollMux_);
|
||||
critical = true;
|
||||
interruptState = maskAllInterrupts();
|
||||
allInterruptsMasked = true;
|
||||
windowEnd = nextStart + pollWindowAfterCycles_;
|
||||
}
|
||||
if (allInterruptsMasked) restoreInterrupts(interruptState);
|
||||
if (critical) portEXIT_CRITICAL(&pollMux_);
|
||||
flushHot();
|
||||
if (__atomic_exchange_n(&core0WdtDisabled_, false,
|
||||
@@ -325,7 +353,7 @@ void DriverTest::processSettling(const TimedEvent &event) {
|
||||
const uint64_t measuredBefore =
|
||||
static_cast<uint64_t>(completedSubsamples_) * subsampleTicks_;
|
||||
const uint64_t thisSubsampleTicks =
|
||||
completedSubsamples_ + 1U == SUBSAMPLE_COUNT ?
|
||||
completedSubsamples_ + 1U == subsampleCount_ ?
|
||||
testTicks_ - measuredBefore : subsampleTicks_;
|
||||
deadlineTick_ = event.tick + thisSubsampleTicks;
|
||||
processTx(event, lightOn);
|
||||
@@ -509,7 +537,7 @@ void DriverTest::completeIfPossible(uint64_t now) {
|
||||
fail(FailReason::DATA_LOSS, lastEventTick_);
|
||||
return;
|
||||
}
|
||||
if (completedSubsamples_ >= SUBSAMPLE_COUNT) {
|
||||
if (completedSubsamples_ >= subsampleCount_) {
|
||||
__atomic_store_n(&progressUpdatePending_, false, __ATOMIC_RELEASE);
|
||||
state_ = DriverState::PASS;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user