Teensy 3.1 GPIO interrupts

Status
Not open for further replies.

timbo

Member
Hello,

I have GPIO interrupt questions (I'm using Teensy 3.1, Ubuntu 12.04, and switching between teensyduino (based on Arduino 1.05) and Eclipse Arduino IDE [EAI] (based on Juno and Arduino 1.5.5)

FYI-My need is to implement an ISR to respond to the falling or rising edge of a pulse. Also, at the moment I'm using pin 20 for PWM output and pin 14 for ADC input. I prefer to operate in EAI.

If there's a complete and upto source for this information please let me know, otherwise I ask for an explanation. I've read many many posts but for many it's hard to determine which teensy
they apply to and I've wasted enough time on useless tangents.

My questions:

1) From a Teensy 3.1 pinout point of view, which (GPIO) pins are available for use detecting this pulse using an interrupt? Or, at least a few candidates that are
likely NOT to interfere with other useful functions. If you want to suggest shifting my PWM and ADC pins around to accommodate a better arrangement plz do so.

2) How do I setup an interrupt ISR for the GPIO pin connected to my pulse?
a) How exactly is the isr function defined?
b) How do I enable interrupts for this behavior, i.e. for rising or falling?
c) How do I "attach" my isr function definition to the enabled interrupt?
d) Are there functions defined that I can use to enable/disable this interrupt at different times?
e) Any cautions about?

I know I have the option of working with registers directly to configure and control but if there's a usable operations for this I want to use them.

3) Can you provide an (complete, i.e. with includes) example?

I know I maybe going against the grain with Eclipse Arduino IDE, but being able to manage build, navigate through code, and better editing features is much less frustrating than Arduino IDE.
So if possible, I'd appreciate a note whether your advise is specific to teensyduino or whether it applies to Eclipse Arduino IDE.

Finally, I soon plan to use interrupts for ADC. If doing so has some not so obvious tricks compared to GPIO interrupts please offer that too.

Thanks in advance.
 
I don't know how much information you have, but pieces to refer to:

From http://www.pjrc.com/teensy/datasheets.html

Download the MK20DX256 Manual. From this you will see there are many ways to configure pins.
Look in Chapter 11 (PORT). You will have to set your pin to GPIO in PORTx_PCRn. Looks like the GPIO interrupt is set with the appropriate bit in PORTx.

The schematic in http://www.pjrc.com/teensy/schematic.html will show the connections between the uP pins and the Arduino pin numbers.

In ...\arduino-1.0.5\hardware\teensy\cores\teensy3 (where Teensyduino was loaded on your system) you will find the files mk20dx128.c and mk20dx128.h . These show the names of the ISR handlers.

In that same directory, look at Tone.cpp. At the end, commented out, is an example of using interrupts.

To use interrupts you need:

Code:
NVIC_ENABLE_IRQ(IRQ_YOUR_INTERRUPT);
in you code.

Then you need the routine

Code:
void yourinterrupt_isr(void){
}
to service your interrupt. Again, the appropriate names are found in mk20dk128

As far as conflict with Arduino resources, I do a Windows text search on the above teensy3 directory to see if the resource I want to use is used anywhere. Don't expect various values to be at reset values. They may have been initialized differently in Teensyduino initialization, so set any variable you are concerned about.

I am using just individual Teensyduino routines with a standalone Makefile, on WindowsXP. If there is additional info on using interrupts out there, I would be interested. This is the information I was able to find. I think it is set up such that if you can figure out the information, you can use interrupts without getting into too much trouble :)

TLB
 
BTW, as far as includes, the only include I have is
Code:
#include "WProgram.h"
from the sample main.cpp in ...\arduino-1.0.5\hardware\teensy\cores\teensy3

I believe that ends up including pretty much everything in that directory. I haven't bothered sorting out what I need and don't need.

TLB
 
Are the NVIC slots centrally/globally managed somewhere in the libs? For example, a function giveMeUnusedVICvectorSlot()
at run time, rather than compile-time.
 
The Vector handler and IRQ numbers are fixed in hardware. (Table 3-4 in the reference manual). mk20dx128.h defines the variable names for these.

Code:
NVIC_ENABLE_IRQ(IRQ_PORTA);
would enable the interrupts from PORTA. Looking thru the initialization code, it looks like these might already be enabled.

TLB
 
tlb,

Thank you for taking the time to help and try and over all that I asked.

Since posting my questions I have experimented with some unqualified hints from a post and they seem to work, but it took a different tact than what you show above.

Here's what I did to establish an ISR for my purpose. I want to describe the basic steps I took, without the obvious details. I accomplished this in Eclipse Arduino IDE.

When I created my project I used "New Sketch". The result was a main file named from the project and an associated header. The header contains a few macros and included Arduino.h, which apparently pulls
in a lot of what I need, including the interrupt related function I used.

Eclipse populated my main cpp file with the setup() and loop() functions. Although I plan to try an eliminate the need for setup() and loop() and get to a more traditional program, I accepted the
given structure and went to the task.

I defined a functions to serve as my ISR, in the form:

void blablaISR(void) {
// handle interrupt.
}

I added to setup():

void setup() {
...
attachInterrupt(pinSync, sync_isr, FALLING); // interrrupt 1 is data ready
...
}

where pinSync defines, in my case, pin 15

And that was it!!

Each time a pulse occurred on pin 15, my isr function was executed.

I'm still wondering, without working directly with registers, how to enable/disable my interrupt source or interrupts in general.
Using Eclipse' navigate feature I found the attachInterrupt() in pins_teensy.c. Odd.

Thanks
 
I'm struggling with this as well. Running a Teensy 3.2.

I have a GPIO ISR which is reading a pin and gets the time (millis()) when it goes low. All works just fine except cli() and sei() do nothing. The only way I can reliably get it to not check interrupts is to detachInterrupt(Pin); and attachInterrupt(Pin, ISR, FALLING);

What do I have wrong? Can I not: attachInterrupt(Pin, ISR, FALLING); in the setup() routine then cli(); to disable it and then use sei(); to enable it when I want to check the Pin? If you need to see the code, I'll have to abstract/simplify it a bit, but this is a question of the use of cli() and sei(). It compiles with the commands in the code with no problem but they do not seem to do anything, or I misunderstand their use. Am I supposed to have an included *.h file I am missing?

I am using Arduino 1.6.8 and Teensyduino 1.28. Previously saw the same behavior with Arduino 1.6.7 and Teensyduino 1.27.

Keith
 
Last edited:
Yes, I have volatile variables. yes it works, I just cannot use cli and sei to disable interrupts. the only way the interrupt gets disabled is if I use attachInterrupt and detachInterrupt

I'll simplify it and post it tomorrow.

THX!
 
Reading your reply - I read more of the p#7. If you don't want to repeatedly attach() & detach() I'd say it would be better to have your isr() just check a 'global' on entry that says "if (isrIgnore) return;". Stopping ALL global interrupts could be a bad thing with regard to any other timers and operations running 'in the background'. Then just set isrIgnore=true; when you want to ignore the interrupt, and isrIgnore=false; when you are interested in what the isr() does.
 
My guess is that attachInterrupt/detachInterrupt is the proper thing to do here.

That is cli/sei - On the Teensy3, these AVR instructions are actually simply defines for
Code:
#define sei() __enable_irq()
#define cli() __disable_irq()
Which if all interrupts are disabled, many of things probably won't work, which rely on interrupts to be serviced. Things like timers, serial ports, ...

Also there are lots of places in code that may set/clear this.
example the detachInterrupt call
Code:
void detachInterrupt(uint8_t pin)
{
	volatile uint32_t *config;

	config = portConfigRegister(pin);
	__disable_irq();
	*config = ((*config & ~0x000F0000) | 0x01000000);
	intFunc[pin] = NULL;
	__enable_irq();
}
Which as you see it itself does the same as cli/sei and when this call completes interrupts are again enabled.

I think your other option to process or not process your pin interrupt, is maybe keep a state flag that the first thing your handler does is see if it is enabled or not... But that still leaves the overhead of having your interrupt be called.
 
I get it now. If I disable interrupts, I have trouble with many of the functions I am trying to use as well as cannot upload code. disable/enableInterrupt is what I have done and things are working correctly.

Thanks for the help!
 
Status
Not open for further replies.
Back
Top