Hi folks,
I've been fighting with the timers on the Maple for a week now and something just isn't adding up. I have a r5 with pin 0 hooked up to my 25 MHz scope and running the following sketch:
#include <timer.h>
void setup() {
SerialUSB.end();
systick_disable();
pinMode(0, OUTPUT);
digitalWrite(0, LOW);
timer_pause(TIMER1);
timer_set_mode(TIMER1, TIMER_CH1, TIMER_OUTPUT_COMPARE);
timer_set_prescaler(TIMER1, 1);
timer_set_reload(TIMER1, 0xffff);
timer_set_compare(TIMER1, TIMER_CH1, 71);
timer_attach_interrupt(TIMER1, TIMER_CH1, handler1);
timer_generate_update(TIMER1);
timer_resume(TIMER1);
}
void handler1() {
GPIOA_BASE->ODR ^= BIT(3);
timer_set_count(TIMER1, 0);
}
void loop() {
for (;;) {
}
}
My intention is to prove to myself that I can count on a 1uS timer but when I run this sketch (from Flash or RAM) I am only seeing output at 150 kHz. So, the interrupt is firing at 300 kHz. This is more than 3x as slow as I would expect.
The way (I think) I have this set up, I would expect the timer to count up at 72 MHz (prescaler 1), and then fire the interrupt when it hits the compare of 71. Since the clock runs at 72 MHz, and I am effectively dividing it by 72 I expect to see the interrupt firing at 1 MHz.
The only thing I can think of is that the interrupt handler takes more than 1uS to execute, but that seems like a long time to me. I believe the Maple is supposed to run instructions at approximately clock speed so that means it should have 72 instructions worth of time to execute the interrupt handler. I'd be surprised to find out that it takes 72 instructions to jump to the handler, flip a bit, set a 16 bit register and return.
Even if it is taking more than 1uS to execute, 3.3uS seems excessively long.
So, any ideas? Suggestions?
I'm open to other ideas on how to do this. The final purpose of the code is to implement a 1 MHz timer that I can use for stepper motor step timing. I will be setting the compare to the time of the next step and then modifying the value on the fly. I need this interrupt to be handled quickly because I will be controlling 4 steppers on the same timer and it's possible that the "next" step value could be very close to the previous one.
-----
Before I finished posting this I decided to try another test.
#include <timer.h>
void setup() {
//SerialUSB.end();
systick_disable();
pinMode(0, OUTPUT);
digitalWrite(0, LOW);
timer_pause(TIMER1);
timer_set_mode(TIMER1, TIMER_CH1, TIMER_OUTPUT_COMPARE);
timer_set_prescaler(TIMER1, 1);
timer_set_reload(TIMER1, 0xffff);
timer_set_compare(TIMER1, TIMER_CH1, 71);
timer_attach_interrupt(TIMER1, TIMER_CH1, handler1);
timer_generate_update(TIMER1);
timer_resume(TIMER1);
}
uint16 a, b;
void handler1() {
a = timer_get_count(TIMER1);
GPIOA_BASE->ODR ^= BIT(3);
b = timer_get_count(TIMER1);
timer_set_count(TIMER1, 0);
}
void loop() {
for (;;) {
delay(1000);
timer_pause(TIMER1);
SerialUSB.print(a, DEC);
SerialUSB.print(" ");
SerialUSB.println(b, DEC);
timer_resume(TIMER1);
}
}
And here's the output:
112 123
113 123
113 123
112 123
112 123
113 123
112 123
113 123
112 123
113 123
113 123
112 123
113 123
113 123
112 123
113 123
112 123
113 123
112 123
112 123
113 123
113 123
112 123
112 123
74 74
112 123
112 123
113 123
113 123
112 123
112 123
112 123
112 123
This is pretty surprising to me. It's taking nearly 40 clocks to get into the interrupt handler and read a 16 bit value?!
Anyone have any suggestions, or want to tell me what I am doing wrong?
Thanks,
Jason