Step timer: reset timer after pauses instead of doing a guess.
We know already wether we start from a pause or not, so let's
take advantage of this knowledge instead of checking for
plausibility of a timer delay at interrupt time.
Costs just 8 bytes binary size:
SIZES ARM... lpc1114
FLASH : 7764 bytes 24%
RAM : 960 bytes 24%
EEPROM : 0 bytes 0%
Due to the less code at interrupt time, maximum step rate was
raised from 127.9 kHz to 130.6 kHz.
This commit is contained in:
parent
f32693bf4e
commit
7afbc70d58
|
|
@ -141,6 +141,7 @@ void enqueue_home(TARGET *t, uint8_t endstop_check, uint8_t endstop_stop_cond) {
|
||||||
ATOMIC_END
|
ATOMIC_END
|
||||||
|
|
||||||
if (isdead) {
|
if (isdead) {
|
||||||
|
timer_reset();
|
||||||
next_move();
|
next_move();
|
||||||
// Compensate for the cli() in timer_set().
|
// Compensate for the cli() in timer_set().
|
||||||
sei();
|
sei();
|
||||||
|
|
|
||||||
34
timer-arm.c
34
timer-arm.c
|
|
@ -144,9 +144,7 @@ void TIMER32_0_IRQHandler(void) {
|
||||||
usually wants to handle this case.
|
usually wants to handle this case.
|
||||||
|
|
||||||
Calls from elsewhere should set it to 0. In this case a timer
|
Calls from elsewhere should set it to 0. In this case a timer
|
||||||
interrupt is always scheduled. At the risk that if this scheduling
|
interrupt is always scheduled.
|
||||||
is too short, the timer doesn't delay the requested time, but up to
|
|
||||||
a full timer counter overflow ( = 2^32 / F_CPU = ~96 seconds).
|
|
||||||
|
|
||||||
\return A flag whether the requested time was too short to allow scheduling
|
\return A flag whether the requested time was too short to allow scheduling
|
||||||
an interrupt. This is meaningful for ACCELERATION_TEMPORAL, where
|
an interrupt. This is meaningful for ACCELERATION_TEMPORAL, where
|
||||||
|
|
@ -189,20 +187,11 @@ uint8_t timer_set(int32_t delay, uint8_t check_short) {
|
||||||
#endif /* ACCELERATION_TEMPORAL */
|
#endif /* ACCELERATION_TEMPORAL */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Still here? Then we can schedule the next step. Usually off of the previous
|
Still here? Then we can schedule the next step. Off of the previous step.
|
||||||
step. If we passed this time already, usually because this is the first
|
If there is no previous step, TC and MR0 should have been reset to zero
|
||||||
move after a pause, we delay off of the current time. Other than on AVR we
|
by calling timer_reset() shortly before we arrive here.
|
||||||
can't affort a full round through the timer here, because this round would
|
|
||||||
be up to 60 seconds.
|
|
||||||
|
|
||||||
TODO: this check costs time and is a plausibility check only. It'd be
|
|
||||||
better to reset the timer from elsewhere when starting a movement
|
|
||||||
after a pause.
|
|
||||||
*/
|
*/
|
||||||
if (LPC_TMR32B0->TC - LPC_TMR32B0->MR0 > delay - 100)
|
LPC_TMR32B0->MR0 += delay;
|
||||||
LPC_TMR32B0->MR0 = LPC_TMR32B0->TC + delay;
|
|
||||||
else
|
|
||||||
LPC_TMR32B0->MR0 += delay;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Turn on the stepper interrupt. As this interrupt is the only use of this
|
Turn on the stepper interrupt. As this interrupt is the only use of this
|
||||||
|
|
@ -213,6 +202,19 @@ uint8_t timer_set(int32_t delay, uint8_t check_short) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Timer reset.
|
||||||
|
|
||||||
|
Reset the timer, so step interrupts scheduled at an arbitrary point in time
|
||||||
|
don't lead to a full round through the timer counter.
|
||||||
|
|
||||||
|
On ARM we actually do something, such a full round through the timer is
|
||||||
|
2^32 / F_CPU = 44 to 90 seconds.
|
||||||
|
*/
|
||||||
|
void timer_reset() {
|
||||||
|
LPC_TMR32B0->TC = 0;
|
||||||
|
LPC_TMR32B0->MR0 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** Stop timers.
|
/** Stop timers.
|
||||||
|
|
||||||
This means to be an emergency stop.
|
This means to be an emergency stop.
|
||||||
|
|
|
||||||
18
timer-avr.c
18
timer-avr.c
|
|
@ -134,9 +134,7 @@ void timer_init() {
|
||||||
usually wants to handle this case.
|
usually wants to handle this case.
|
||||||
|
|
||||||
Calls from elsewhere should set it to 0. In this case a timer
|
Calls from elsewhere should set it to 0. In this case a timer
|
||||||
interrupt is always scheduled. At the risk that if this scheduling
|
interrupt is always scheduled.
|
||||||
is too short, the timer doesn't delay the requested time, but up to
|
|
||||||
a full timer counter overflow ( = 65536 / F_CPU = 3 to 4 milliseconds).
|
|
||||||
|
|
||||||
\return A flag whether the requested time was too short to allow scheduling
|
\return A flag whether the requested time was too short to allow scheduling
|
||||||
an interrupt. This is meaningful for ACCELERATION_TEMPORAL, where
|
an interrupt. This is meaningful for ACCELERATION_TEMPORAL, where
|
||||||
|
|
@ -149,8 +147,7 @@ void timer_init() {
|
||||||
time of the call, but starting at the time of the previous timer interrupt
|
time of the call, but starting at the time of the previous timer interrupt
|
||||||
fired. This ignores the processing time taken in the step interrupt so far,
|
fired. This ignores the processing time taken in the step interrupt so far,
|
||||||
offering smooth and even step distribution. Flipside of this coin is,
|
offering smooth and even step distribution. Flipside of this coin is,
|
||||||
schedules issued at an arbitrary time can result in drastically wrong delays.
|
one has to call timer_reset() before scheduling a step at an arbitrary time.
|
||||||
See also discussion of parameter check_short and the return value.
|
|
||||||
|
|
||||||
This enables the step interrupt, but also disables interrupts globally.
|
This enables the step interrupt, but also disables interrupts globally.
|
||||||
So, if you use it from inside the step interrupt, make sure to do so
|
So, if you use it from inside the step interrupt, make sure to do so
|
||||||
|
|
@ -220,6 +217,17 @@ uint8_t timer_set(int32_t delay, uint8_t check_short) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Timer reset.
|
||||||
|
|
||||||
|
Reset the timer, so step interrupts scheduled at an arbitrary point in time
|
||||||
|
don't lead to a full round through the timer counter.
|
||||||
|
|
||||||
|
On AVR we simply do nothing, such a full round through the timer is just
|
||||||
|
2^16 / F_CPU = 3 to 4 milliseconds.
|
||||||
|
*/
|
||||||
|
void timer_reset() {
|
||||||
|
}
|
||||||
|
|
||||||
/** Stop timers.
|
/** Stop timers.
|
||||||
|
|
||||||
This means to be an emergency stop.
|
This means to be an emergency stop.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue