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
|
||||
|
||||
if (isdead) {
|
||||
timer_reset();
|
||||
next_move();
|
||||
// Compensate for the cli() in timer_set().
|
||||
sei();
|
||||
|
|
|
|||
34
timer-arm.c
34
timer-arm.c
|
|
@ -144,9 +144,7 @@ void TIMER32_0_IRQHandler(void) {
|
|||
usually wants to handle this case.
|
||||
|
||||
Calls from elsewhere should set it to 0. In this case a timer
|
||||
interrupt is always scheduled. At the risk that if this scheduling
|
||||
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).
|
||||
interrupt is always scheduled.
|
||||
|
||||
\return A flag whether the requested time was too short to allow scheduling
|
||||
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 */
|
||||
|
||||
/**
|
||||
Still here? Then we can schedule the next step. Usually off of the previous
|
||||
step. If we passed this time already, usually because this is the first
|
||||
move after a pause, we delay off of the current time. Other than on AVR we
|
||||
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.
|
||||
Still here? Then we can schedule the next step. Off of the previous step.
|
||||
If there is no previous step, TC and MR0 should have been reset to zero
|
||||
by calling timer_reset() shortly before we arrive here.
|
||||
*/
|
||||
if (LPC_TMR32B0->TC - LPC_TMR32B0->MR0 > delay - 100)
|
||||
LPC_TMR32B0->MR0 = LPC_TMR32B0->TC + delay;
|
||||
else
|
||||
LPC_TMR32B0->MR0 += delay;
|
||||
LPC_TMR32B0->MR0 += delay;
|
||||
|
||||
/**
|
||||
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;
|
||||
}
|
||||
|
||||
/** 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.
|
||||
|
||||
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.
|
||||
|
||||
Calls from elsewhere should set it to 0. In this case a timer
|
||||
interrupt is always scheduled. At the risk that if this scheduling
|
||||
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).
|
||||
interrupt is always scheduled.
|
||||
|
||||
\return A flag whether the requested time was too short to allow scheduling
|
||||
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
|
||||
fired. This ignores the processing time taken in the step interrupt so far,
|
||||
offering smooth and even step distribution. Flipside of this coin is,
|
||||
schedules issued at an arbitrary time can result in drastically wrong delays.
|
||||
See also discussion of parameter check_short and the return value.
|
||||
one has to call timer_reset() before scheduling a step at an arbitrary time.
|
||||
|
||||
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
|
||||
|
|
@ -220,6 +217,17 @@ uint8_t timer_set(int32_t delay, uint8_t check_short) {
|
|||
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.
|
||||
|
||||
This means to be an emergency stop.
|
||||
|
|
|
|||
Loading…
Reference in New Issue