1
0
mirror of https://github.com/bdring/Grbl_Esp32.git synced 2025-08-30 01:30:05 +02:00

Replace esp_delay_us() with ISR-friendly code in IRAM

This commit is contained in:
Mitch Bradley
2021-07-16 09:32:49 -10:00
parent 9506992f6e
commit ce7fffd6e4
8 changed files with 50 additions and 19 deletions

View File

@@ -24,6 +24,8 @@
// #define true 1
#include <cstdint>
#include <esp_attr.h>
#include <xtensa/core-macros.h>
enum class DwellMode : uint8_t {
Dwell = 0, // (Default: Must be zero)
@@ -93,6 +95,9 @@ const float INCH_PER_MM = (0.0393701f);
// a pointer to the result variable. Returns true when it succeeds
uint8_t read_float(const char* line, uint8_t* char_counter, float* float_ptr);
// Blocking delay for very short time intervals
void delay_us(int32_t microseconds);
// Non-blocking delay function used for general operation and suspend features.
bool delay_msec(int32_t milliseconds, DwellMode mode);
@@ -118,3 +123,38 @@ void swap(T& a, T& b) {
a = b;
b = c;
}
// Short delays measured using the CPU cycle counter. There is a ROM
// routine "esp_delay_us(us)" that almost does what what we need,
// except that it is in ROM and thus dodgy for use from ISRs. We
// duplicate the esp_delay_us() here, but placed in IRAM, inlined,
// and factored so it can be used in different ways.
inline int32_t IRAM_ATTR getCpuTicks() {
return XTHAL_GET_CCOUNT();
}
extern uint32_t g_ticks_per_us_pro; // For CPU 0 - typically 240 MHz
extern uint32_t g_ticks_per_us_app; // For CPU 1 - typically 240 MHz
inline int32_t IRAM_ATTR usToCpuTicks(int32_t us) {
return us * g_ticks_per_us_pro;
}
inline int32_t IRAM_ATTR usToEndTicks(int32_t us) {
return getCpuTicks() + usToCpuTicks(us);
}
// At the usual ESP32 clock rate of 240MHz, the range of this is
// just under 18 seconds, but it really should be used only for
// short delays up to a few tens of microseconds.
inline void IRAM_ATTR spinUntil(int32_t endTicks) {
while ((XTHAL_GET_CCOUNT() - endTicks) < 0) {
asm volatile("nop");
}
}
inline void IRAM_ATTR delay_us(int32_t us) {
spinUntil(usToEndTicks(us));
}

View File

@@ -52,7 +52,7 @@ namespace Spindles {
}
set_output(dev_speed);
set_enable(state != SpindleState::Disable);
spinDelay(state, speed);
spindleDelay(state, speed);
sys.report_ovr_counter = 0; // Set to report change immediately
}

View File

@@ -112,7 +112,7 @@ namespace Spindles {
// converters on some boards.
set_output(dev_speed);
set_enable(state != SpindleState::Disable);
spinDelay(state, speed);
spindleDelay(state, speed);
sys.report_ovr_counter = 0; // Set to report change immediately
}

View File

@@ -140,7 +140,7 @@ namespace Spindles {
// log_debug("rpm " << speed << " speed " << dev_speed); // This will spew quite a bit of data on your output
return dev_speed;
}
void Spindle::spinDelay(SpindleState state, SpindleSpeed speed) {
void Spindle::spindleDelay(SpindleState state, SpindleSpeed speed) {
uint32_t up = 0, down = 0;
switch (state) {
case SpindleState::Unknown:

View File

@@ -59,7 +59,7 @@ namespace Spindles {
static void switchSpindle(uint8_t new_tool, SpindleList spindles, Spindle*& spindle);
void spinDelay(SpindleState state, SpindleSpeed speed);
void spindleDelay(SpindleState state, SpindleSpeed speed);
virtual void init() = 0; // not in constructor because this also gets called when $$ settings change
// Used by Protocol.cpp to restore the state during a restart

View File

@@ -345,7 +345,7 @@ namespace Spindles {
}
}
if (!supports_actual_speed()) {
spinDelay(state, speed);
spindleDelay(state, speed);
} else {
// _sync_dev_speed is set by a callback that handles
// responses from periodic get_current_speed() requests.
@@ -386,7 +386,7 @@ namespace Spindles {
}
_syncing = false;
// spinDelay() sets these when it is used
// spindleDelay() sets these when it is used
_current_state = state;
_current_speed = speed;
}

View File

@@ -73,13 +73,6 @@ namespace Machine {
_engine = I2S_STREAM;
}
}
void IRAM_ATTR Stepping::spinDelay(int64_t start_time, uint32_t durationUs) {
int64_t endTime = start_time + durationUs;
while ((esp_timer_get_time() - endTime) < 0) {
NOP();
}
}
void IRAM_ATTR Stepping::waitPulse() {
uint64_t pulseEndTime;
switch (_engine) {
@@ -90,7 +83,7 @@ namespace Machine {
case I2S_STATIC:
i2s_out_push();
case TIMED:
spinDelay(_stepPulseStartTime, _pulseUsecs);
spinUntil(_stepPulseEndTime);
break;
case RMT:
// RMT generates the trailing edges in hardware
@@ -112,7 +105,7 @@ namespace Machine {
// If we are using GPIO stepping as opposed to RMT, record the
// time that we turned on the direction pins so we can delay a bit.
// If we are using RMT, we can't delay here.
spinDelay(esp_timer_get_time(), _directionDelayUsecs);
delay_us(_directionDelayUsecs);
break;
case stepper_id_t::RMT:
break;
@@ -126,7 +119,7 @@ namespace Machine {
break;
case stepper_id_t::I2S_STATIC:
case stepper_id_t::TIMED:
_stepPulseStartTime = esp_timer_get_time();
_stepPulseEndTime = usToEndTicks(_pulseUsecs);
break;
case stepper_id_t::RMT:
break;

View File

@@ -35,9 +35,7 @@ namespace Machine {
static const int ticksPerMicrosecond = fStepperTimer / 1000000;
bool _switchedStepper = false;
int64_t _stepPulseStartTime;
static void spinDelay(int64_t start_time, uint32_t duration);
int32_t _stepPulseEndTime;
public:
// Counts stepper ISR invocations. This variable can be inspected