diff --git a/dda_queue.c b/dda_queue.c index 3b1e153..9cb8b9d 100644 --- a/dda_queue.c +++ b/dda_queue.c @@ -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(); diff --git a/timer-arm.c b/timer-arm.c index 58f9e82..a1df4fa 100644 --- a/timer-arm.c +++ b/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. diff --git a/timer-avr.c b/timer-avr.c index 3fbeaaf..f8be16a 100644 --- a/timer-avr.c +++ b/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. diff --git a/timer.h b/timer.h index 0cd6ac7..386ed6d 100644 --- a/timer.h +++ b/timer.h @@ -21,6 +21,8 @@ void timer_init(void); uint8_t timer_set(int32_t delay, uint8_t check_short); +void timer_reset(void); + void timer_stop(void); #endif /* _TIMER_H */