Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ad9af53

Browse filesBrowse files
committed
Alternate CPU frequency scaling mitigation.
1 parent 69e2016 commit ad9af53
Copy full SHA for ad9af53

File tree

Expand file treeCollapse file tree

1 file changed

+29
-21
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+29
-21
lines changed

‎cores/esp8266/core_esp8266_waveform.cpp

Copy file name to clipboardExpand all lines: cores/esp8266/core_esp8266_waveform.cpp
+29-21Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ constexpr int32_t MAXIRQTICKSCCYS = microsecondsToClockCycles(10000);
5151
// Maximum servicing time for any single IRQ
5252
constexpr uint32_t ISRTIMEOUTCCYS = microsecondsToClockCycles(18);
5353
// The latency between in-ISR rearming of the timer and the earliest firing
54-
constexpr int32_t IRQLATENCYCCYS = microsecondsToClockCycles(2);
54+
constexpr int32_t IRQLATENCYCCYS = ISCPUFREQ160MHZ ?
55+
microsecondsToClockCycles(2) >> 1 : microsecondsToClockCycles(2);
56+
// The SDK and hardware take some time to actually get to our NMI code
57+
constexpr int32_t DELTAIRQCCYS = ISCPUFREQ160MHZ ?
58+
microsecondsToClockCycles(2) >> 1 : microsecondsToClockCycles(2);
5559

5660
// for INFINITE, the NMI proceeds on the waveform without expiry deadline.
5761
// for EXPIRES, the NMI expires the waveform automatically on the expiry ccy.
@@ -251,8 +255,9 @@ static inline ICACHE_RAM_ATTR int32_t scaleCcys(const int32_t ccys, const bool i
251255
}
252256

253257
static ICACHE_RAM_ATTR void timer1Interrupt() {
254-
const bool isCPU2X = CPU2X & 1;
255258
const uint32_t isrStartCcy = ESP.getCycleCount();
259+
int32_t clockDrift = isrStartCcy - waveform.nextEventCcy - DELTAIRQCCYS;
260+
const bool isCPU2X = CPU2X & 1;
256261
if ((waveform.toSetBits && !(waveform.enabled & waveform.toSetBits)) || waveform.toDisableBits) {
257262
// Handle enable/disable requests from main app.
258263
waveform.enabled = (waveform.enabled & ~waveform.toDisableBits) | waveform.toSetBits; // Set the requested waveforms on/off
@@ -268,13 +273,9 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
268273
waveform.states &= ~waveform.toSetBits; // Clear the state of any just started
269274
if (wave.alignPhase >= 0 && waveform.enabled & (1UL << wave.alignPhase)) {
270275
wave.nextPeriodCcy = waveform.pins[wave.alignPhase].nextPeriodCcy + wave.nextPeriodCcy;
271-
if (static_cast<int32_t>(waveform.nextEventCcy - wave.nextPeriodCcy) > 0) {
272-
waveform.nextEventCcy = wave.nextPeriodCcy;
273-
}
274276
}
275277
else {
276-
wave.nextPeriodCcy = isrStartCcy;
277-
waveform.nextEventCcy = wave.nextPeriodCcy;
278+
wave.nextPeriodCcy = waveform.nextEventCcy;
278279
}
279280
if (!wave.expiryCcy) {
280281
wave.mode = WaveformMode::INFINITE;
@@ -294,10 +295,8 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
294295

295296
// Exit the loop if the next event, if any, is sufficiently distant.
296297
const uint32_t isrTimeoutCcy = isrStartCcy + ISRTIMEOUTCCYS;
297-
uint32_t busyPins = (static_cast<int32_t>(waveform.nextEventCcy - isrTimeoutCcy) < 0) ? waveform.enabled : 0;
298-
if (!waveform.enabled || busyPins) {
299-
waveform.nextEventCcy = isrStartCcy + MAXIRQTICKSCCYS;
300-
}
298+
uint32_t busyPins = waveform.enabled;
299+
waveform.nextEventCcy = isrStartCcy + MAXIRQTICKSCCYS;
301300

302301
uint32_t now = ESP.getCycleCount();
303302
uint32_t isrNextEventCcy = now;
@@ -315,6 +314,12 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
315314

316315
Waveform& wave = waveform.pins[pin];
317316

317+
if (clockDrift) {
318+
wave.endDutyCcy += clockDrift;
319+
wave.nextPeriodCcy += clockDrift;
320+
wave.expiryCcy += clockDrift;
321+
}
322+
318323
uint32_t waveNextEventCcy = (waveform.states & pinBit) ? wave.endDutyCcy : wave.nextPeriodCcy;
319324
if (WaveformMode::EXPIRES == wave.mode &&
320325
static_cast<int32_t>(waveNextEventCcy - wave.expiryCcy) >= 0 &&
@@ -394,29 +399,32 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
394399
}
395400
now = ESP.getCycleCount();
396401
}
402+
clockDrift = 0;
397403
}
398404

399405
int32_t callbackCcys = 0;
400406
if (waveform.timer1CB) {
401407
callbackCcys = scaleCcys(microsecondsToClockCycles(waveform.timer1CB()), isCPU2X);
402408
}
403409
now = ESP.getCycleCount();
404-
int32_t nextTimerCcys = waveform.nextEventCcy - now;
410+
int32_t nextEventCcys = waveform.nextEventCcy - now;
405411
// Account for unknown duration of timer1CB().
406-
if (waveform.timer1CB && nextTimerCcys > callbackCcys) {
407-
nextTimerCcys = callbackCcys;
412+
if (waveform.timer1CB && nextEventCcys > callbackCcys) {
413+
waveform.nextEventCcy = now + callbackCcys;
414+
nextEventCcys = callbackCcys;
408415
}
409416

410-
// Firing timer too soon, the NMI occurs before ISR has returned.
411-
if (nextTimerCcys < IRQLATENCYCCYS) {
412-
nextTimerCcys = IRQLATENCYCCYS;
417+
// Timer is 80MHz fixed. 160MHz CPU frequency need scaling.
418+
if (isCPU2X) {
419+
nextEventCcys >>= 1;
413420
}
414421

415-
// Timer is 80MHz fixed. 160MHz CPU frequency need scaling.
416-
if (ISCPUFREQ160MHZ || isCPU2X) {
417-
nextTimerCcys >>= 1;
422+
// Firing timer too soon, the NMI occurs before ISR has returned.
423+
if (nextEventCcys < IRQLATENCYCCYS) {
424+
waveform.nextEventCcy = now + IRQLATENCYCCYS;
425+
nextEventCcys = IRQLATENCYCCYS;
418426
}
419427

420428
// Register access is fast and edge IRQ was configured before.
421-
T1L = nextTimerCcys;
429+
T1L = nextEventCcys;
422430
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.