## Thursday, January 10, 2013

### Periodic Interrupt Timers on the Teensy 3.0 (Freescale MK20DX128)

After getting the software, I was able to write a standard Arduino sketch to blink the LED connected to pin 13.  The code is below:

void setup(){
pinMode(13, OUTPUT);
}

void loop(){
digitalWrite( 13, HIGH );
delay( 100 );
delay( 100 )
}


It's pretty nice that the Teensy3 works like a regular Arduino, but with more pins, at a higher clock rate, in 32 bits and with heaps of extra peripherals.  However my end goal is to use the board as a CNC controller for my ongoing firmware project.  This will make extensive use of timed interrupts to control steppers, so I thought I'd try to get timers working.  Of course, the Teensy3 is not a Atmel uC, so everything changes at this point and, with the help of this forum post to get started, I had to dive into the manual (available from here) for the Freescale MK20DX128 that the Teensy3 is based upon.

According to the forum post, the timer to use is one of the (4?) Periodic Interrupt Timers (PITs).  As expected, these have a number of control registers. Registers listed with an [N], e.g. PIT_LDVAL[N] should have an appropriate timer index substituted, like PIT_LDVAL2.  Here are the registers:
• SIM_SCGC6 - Enables/disables clock used by PIT timers, not exactly clear on the details, set to SIM_SCGC6_PIT in the forum post example.
• PIT_MCR - Enables and disables the PIT timers. Writing zero enables the timers and writing 1 disables them.
• PIT_LDVAL[N] - Sets the timer count value.  Apparently the timer runs at 50MHz, so toggling timer 2 every second should set PIT_LDVAL2 to 0x2fa080 (hex for 50,000,000).  Visually, this appears to be around a second.
• PIT_TCTRL[N] - Bit zero (TEN in the manual) enables (set to 1) or disables (set to zero) the timer. Bit one (TIE in the manual) enables (set to 1) or disables (set to zero) interrupts that can be generated by the timer.
• PIT_TFLG[N] - Flag to indicate timer waiting.  Set to one to start timer and at the end of every called interrupt routine, otherwise interrupts will stop.
Finally, interupts must be enabled. Again I'm not clear on the details, but calling NVIC_ENABLE_IRQ( IRC_PIT_CH[N] ) results in the interupt "void pit[N]_isr(void){}" being called.  Although it seems like the chip should have four timers, I only succeeded in getting timers 0, 1, and 2 working properly with interrupts, testing with index 3 gave a linker error in the Arduino software.

Anyway, here's the code for my tests:

#define TIE 0x2
#define TEN 0x1

void pit0_isr(void){
PIT_TFLG0 = 1;
}

void setup(){
pinMode(13,OUTPUT);
SIM_SCGC6 |= SIM_SCGC6_PIT;
PIT_MCR = 0x00;
NVIC_ENABLE_IRQ(IRQ_PIT_CH0);
PIT_LDVAL0 = 0x2faf080;
PIT_TCTRL0 = TIE;
PIT_TCTRL0 |= TEN;
PIT_TFLG0 |= 1;
}

void loop(){
delay(2000);
}


Hope this helps someone get up to speed, and perhaps serves as a reference for me later on.

drf5n said...

FTM1 might be an alternative to the PIT -- Perhaps you could trade the PWM ability on pins 2 & 3 for one of use of one the flexible timer modules. Then not have to worry about re-adjusting the period of the Periodic Interrupt Timers as the time between steps changes.

James Gregson said...

Thanks for the suggestion, I'll look into these!

James

james a munsch said...
This comment has been removed by the author.
james a munsch said...

I think this might be relevant.

https://github.com/loglow/IntervalTimer

The discussion related to this can be found here: http://forum.pjrc.com/threads/17543-PITimer-PIT-%28Periodic-Interrupt-Timer%29-library-for-Teensy-3-0/page2