Set a minimum delay instead of attempting to call the timer interrupt
service routine in the case that the requested timer interval is too small. Calling the interrupt service routine at this point is likely to recursively clobber the stack. Setting a lower bounds on the interrupt delay will limit the upper speed of pulse generation, but it should not change the relative pulse rates, and will not recurvisely clobber the stack. Note that the lower limit of 17 has not been researched, it is simply the value below which the old code attempted to call the interrupt service routine directly.
This commit is contained in:
parent
8241549276
commit
57b30b0ff1
62
timer.c
62
timer.c
|
|
@ -124,6 +124,12 @@ void timer_init()
|
||||||
/// specify how long until the step timer should fire
|
/// specify how long until the step timer should fire
|
||||||
void setTimer(uint32_t delay)
|
void setTimer(uint32_t delay)
|
||||||
{
|
{
|
||||||
|
// if the delay is too small use a minimum delay so that there is time
|
||||||
|
// to set everything up before the timer expires.
|
||||||
|
|
||||||
|
if (delay < 17 )
|
||||||
|
delay = 17;
|
||||||
|
|
||||||
// save interrupt flag
|
// save interrupt flag
|
||||||
uint8_t sreg = SREG;
|
uint8_t sreg = SREG;
|
||||||
uint16_t step_start = 0;
|
uint16_t step_start = 0;
|
||||||
|
|
@ -136,40 +142,34 @@ void setTimer(uint32_t delay)
|
||||||
TIMSK1 |= MASK(OCIE1B);
|
TIMSK1 |= MASK(OCIE1B);
|
||||||
|
|
||||||
if (delay > 0) {
|
if (delay > 0) {
|
||||||
if (delay <= 16) {
|
|
||||||
// unfortunately, force registers don't trigger an interrupt, so we do the following
|
// Assume all steps belong to one move. Within one move the delay is
|
||||||
// "fire" ISR- maybe it sets a new timeout
|
// from one step to the next one, which should be more or less the same
|
||||||
timer1_compa_isr();
|
// as from one step interrupt to the next one. The last step interrupt happend
|
||||||
|
// at OCR1A, so start delay from there.
|
||||||
|
step_start = OCR1A;
|
||||||
|
if (next_step_time == 0) {
|
||||||
|
// new move, take current time as start value
|
||||||
|
step_start = TCNT1;
|
||||||
|
}
|
||||||
|
|
||||||
|
next_step_time = delay;
|
||||||
|
if (next_step_time < 65536) {
|
||||||
|
// set the comparator directly to the next real step
|
||||||
|
OCR1A = (next_step_time + step_start) & 0xFFFF;
|
||||||
|
}
|
||||||
|
else if (next_step_time < 75536) {
|
||||||
|
// Next comparator interrupt would have to trigger another
|
||||||
|
// interrupt within a short time (possibly within 1 cycle).
|
||||||
|
// Avoid the impossible by firing the interrupt earlier.
|
||||||
|
OCR1A = (step_start - 10000) & 0xFFFF;
|
||||||
|
next_step_time += 10000;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Assume all steps belong to one move. Within one move the delay is
|
OCR1A = step_start;
|
||||||
// from one step to the next one, which should be more or less the same
|
|
||||||
// as from one step interrupt to the next one. The last step interrupt happend
|
|
||||||
// at OCR1A, so start delay from there.
|
|
||||||
step_start = OCR1A;
|
|
||||||
if (next_step_time == 0) {
|
|
||||||
// new move, take current time as start value
|
|
||||||
step_start = TCNT1;
|
|
||||||
}
|
|
||||||
|
|
||||||
next_step_time = delay;
|
|
||||||
if (next_step_time < 65536) {
|
|
||||||
// set the comparator directly to the next real step
|
|
||||||
OCR1A = (next_step_time + step_start) & 0xFFFF;
|
|
||||||
}
|
|
||||||
else if (next_step_time < 75536) {
|
|
||||||
// Next comparator interrupt would have to trigger another
|
|
||||||
// interrupt within a short time (possibly within 1 cycle).
|
|
||||||
// Avoid the impossible by firing the interrupt earlier.
|
|
||||||
OCR1A = (step_start - 10000) & 0xFFFF;
|
|
||||||
next_step_time += 10000;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
OCR1A = step_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
TIMSK1 |= MASK(OCIE1A);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TIMSK1 |= MASK(OCIE1A);
|
||||||
} else {
|
} else {
|
||||||
// flag: move has ended
|
// flag: move has ended
|
||||||
next_step_time = 0;
|
next_step_time = 0;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue