PDA

View Full Version : Detect Teensy 3.0



teckel
11-15-2012, 08:08 AM
With libraries I'm the author of (NewPing, LCDBitmap, and others) I detect Teensy 2.0 hardware with the following (not complete code):

#if defined (__AVR_ATmega32U4__)
#if defined (CORE_TEENSY)

Is there a proper method of detecting the Teensy 3.0 and/or the Freescale microcontroller? My libraries use port registers, so platform detection will be required for Teensy 3.0 compatibly.

Thanks!

Tim

PaulStoffregen
11-15-2012, 11:29 AM
You can use #if defined(__MK20DX128__) to check for Teensy 3.0.

Teensy 3.0 has some AVR emulation code for PORTB, PORTD and PORTC to map bit operations to direct manipulation of the Freescale port registers. The register to pin mapping attempts to emulate Arduino Uno. If you write "PORTB |= (1<<5)", the compiled code is a a single-bus-cycle write to set pin 13 high. Even though you're running on a 32 bit ARM, this common AVR-specific code works.

Of your libraries use direct AVR registers and you default to Uno's well known register mapping when all the other #if checks don't match (as is commonly done with lots of libraries), there's a good chance much of it may "just work" on Teensy 3.0. :)

teckel
11-15-2012, 09:24 PM
Where I run into trouble with using Teensy 3.0 is when setting the pin mode via port registers, not setting a pin high or low. For example:



uint8_t _pinBit = digitalPinToBitMask(pin);
volatile uint8_t *_pinMode = (uint8_t *) portModeRegister(digitalPinToPort(pin));

*_pinMode |= _pinBit; // Set pin to output

I set _pinBit and _pinMode based on the pin and then set the pin to output. However, setting the pin to output with Teensy 3.0 works differently, like this:



volatile uint32_t *_pinConfig = portConfigRegister(pin);
*portModeRegister(pin) = 1;
*_pinConfig = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);

In my code, whenever I need to set a pin to input or output, I just do:



*_pinMode &= ~_pinBit; // Set pin to input.
*_pinMode |= _pinBit; // Set pin to output.

Unless I'm missing something, that needs to be changed to what's shown above for output or what's below for input:



volatile uint32_t *_pinConfig = portConfigRegister(pin);
*portModeRegister(pin) = 0;
*config = PORT_PCR_MUX(1);

So, for setting a pin high or low, you are correct. It's setting of the pin mode via port registers that's the problem. I haven't even got to reading a digital port yet, but there could be issues there as well as I'm doing a check like this *_pinInput & _pinBit but with Teensy 3.0 it's done with *portInputRegister(pin) (and my current code doesn't even hold the pin value as it accesses everything by port registers.

Also, some methods are using timers (timer 2 on ATmega328 and timer 4 on Teensy 2.0). So, I get a bunch of errors on the Teensy 3.0. Obviously, timers are all totally different, so the __MK20DX128__ will do nicely to remove methods that use timers. With every pin on the Teensy 3.0 having an external pin interrupt, there's no reason for me to even use timers with Teensy 3.0.

Tim