Browse Source

Initial support for Teensy-LC

teensy4-core
PaulStoffregen 10 years ago
parent
commit
9b8d74c089
20 changed files with 1722 additions and 303 deletions
  1. +9
    -1
      teensy3/HardwareSerial.h
  2. +20
    -2
      teensy3/IntervalTimer.cpp
  3. +13
    -1
      teensy3/IntervalTimer.h
  4. +7
    -2
      teensy3/SPIFIFO.h
  5. +23
    -98
      teensy3/Tone.cpp
  6. +66
    -10
      teensy3/analog.c
  7. +329
    -42
      teensy3/avr_emulation.h
  8. +315
    -7
      teensy3/core_pins.h
  9. +224
    -1
      teensy3/kinetis.h
  10. +136
    -14
      teensy3/mk20dx128.c
  11. +110
    -0
      teensy3/mkl26z64.ld
  12. +53
    -9
      teensy3/pins_arduino.h
  13. +255
    -101
      teensy3/pins_teensy.c
  14. +49
    -0
      teensy3/ser_print.c
  15. +11
    -0
      teensy3/ser_print.h
  16. +56
    -3
      teensy3/serial1.c
  17. +6
    -0
      teensy3/serial2.c
  18. +6
    -0
      teensy3/serial3.c
  19. +29
    -7
      teensy3/touch.c
  20. +5
    -5
      teensy3/usb_dev.c

+ 9
- 1
teensy3/HardwareSerial.h View File

@@ -85,8 +85,16 @@
// bit7: actual data goes into 9th bit


#if defined(KINETISK)
#define BAUD2DIV(baud) (((F_CPU * 2) + ((baud) >> 1)) / (baud))
#define BAUD2DIV2(baud) (((F_CPU * 2) + ((baud) >> 1)) / (baud))
#define BAUD2DIV3(baud) (((F_BUS * 2) + ((baud) >> 1)) / (baud))
#elif defined(KINETISL)
#define BAUD2DIV(baud) (((F_PLL / 2 / 16) + ((baud) >> 1)) / (baud))
#define BAUD2DIV2(baud) (((F_BUS / 16) + ((baud) >> 1)) / (baud))
#define BAUD2DIV3(baud) (((F_BUS / 16) + ((baud) >> 1)) / (baud))
#endif


// C language implementation
//
@@ -178,7 +186,7 @@ extern void serialEvent1(void);
class HardwareSerial2 : public HardwareSerial
{
public:
virtual void begin(uint32_t baud) { serial2_begin(BAUD2DIV(baud)); }
virtual void begin(uint32_t baud) { serial2_begin(BAUD2DIV2(baud)); }
virtual void begin(uint32_t baud, uint32_t format) {
serial2_begin(BAUD2DIV(baud));
serial2_format(format); }

+ 20
- 2
teensy3/IntervalTimer.cpp View File

@@ -36,11 +36,20 @@ IntervalTimer::ISR IntervalTimer::PIT_ISR[];
// so that they can auto-clear themselves and so the user can
// specify a custom ISR and reassign it as needed
// ------------------------------------------------------------
#if defined(KINETISK)
void pit0_isr() { PIT_TFLG0 = 1; IntervalTimer::PIT_ISR[0](); }
void pit1_isr() { PIT_TFLG1 = 1; IntervalTimer::PIT_ISR[1](); }
void pit2_isr() { PIT_TFLG2 = 1; IntervalTimer::PIT_ISR[2](); }
void pit3_isr() { PIT_TFLG3 = 1; IntervalTimer::PIT_ISR[3](); }

#elif defined(KINETISL)
void pit_isr() {
if (PIT_TFLG0) { PIT_TFLG0 = 1; IntervalTimer::PIT_ISR[0](); }
if (!IntervalTimer::PIT_enabled) return;
if (PIT_TFLG1) { PIT_TFLG1 = 1; IntervalTimer::PIT_ISR[1](); }
}
#endif



// ------------------------------------------------------------
@@ -143,7 +152,6 @@ void IntervalTimer::start_PIT(uint32_t newValue) {
// point to the correct registers
PIT_LDVAL = &PIT_LDVAL0 + PIT_id * 4;
PIT_TCTRL = &PIT_TCTRL0 + PIT_id * 4;
IRQ_PIT_CH = IRQ_PIT_CH0 + PIT_id;
// point to the correct PIT ISR
PIT_ISR[PIT_id] = myISR;
@@ -152,8 +160,14 @@ void IntervalTimer::start_PIT(uint32_t newValue) {
*PIT_TCTRL = 0;
*PIT_LDVAL = newValue;
*PIT_TCTRL = 3;
#if defined(KINETISK)
IRQ_PIT_CH = IRQ_PIT_CH0 + PIT_id;
NVIC_SET_PRIORITY(IRQ_PIT_CH, nvic_priority);
NVIC_ENABLE_IRQ(IRQ_PIT_CH);
#elif defined(KINETISL)
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priority); // TODO: use the higher of both channels, shared irq
NVIC_ENABLE_IRQ(IRQ_PIT);
#endif

}

@@ -167,8 +181,12 @@ void IntervalTimer::start_PIT(uint32_t newValue) {
void IntervalTimer::stop_PIT() {
// disable interrupt and PIT
NVIC_DISABLE_IRQ(IRQ_PIT_CH);
*PIT_TCTRL = 0;
#if defined(KINETISK)
NVIC_DISABLE_IRQ(IRQ_PIT_CH);
#elif defined(KINETISL)
NVIC_DISABLE_IRQ(IRQ_PIT);
#endif
// free PIT for future use
PIT_used[PIT_id] = false;

+ 13
- 1
teensy3/IntervalTimer.h View File

@@ -32,12 +32,17 @@ class IntervalTimer {
typedef void (*ISR)();
typedef volatile uint32_t* reg;
enum {TIMER_OFF, TIMER_PIT};
#if defined(KINETISK)
static const uint8_t NUM_PIT = 4;
#elif defined(KINETISL)
static const uint8_t NUM_PIT = 2;
#endif
static const uint32_t MAX_PERIOD = UINT32_MAX / (F_BUS / 1000000.0);
static void enable_PIT();
static void disable_PIT();
static bool PIT_enabled;
static bool PIT_used[NUM_PIT];
static ISR PIT_ISR[NUM_PIT];
bool allocate_PIT(uint32_t newValue);
void start_PIT(uint32_t newValue);
void stop_PIT();
@@ -81,7 +86,14 @@ class IntervalTimer {
nvic_priority = n;
if (PIT_enabled) NVIC_SET_PRIORITY(IRQ_PIT_CH, n);
}
static ISR PIT_ISR[NUM_PIT];
#if defined(KINETISK)
friend void pit0_isr();
friend void pit1_isr();
friend void pit2_isr();
friend void pit3_isr();
#elif defined(KINETISL)
friend void pit_isr();
#endif
};



+ 7
- 2
teensy3/SPIFIFO.h View File

@@ -3,6 +3,8 @@

#include "avr_emulation.h"

#ifdef KINETISK

#if F_BUS == 60000000
#define HAS_SPIFIFO
#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(60 / 3) * ((1+1)/2) = 20 MHz
@@ -93,7 +95,9 @@
#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz
#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz

#endif
#endif // F_BUS

#endif // KINETISK

/*
#! /usr/bin/perl
@@ -228,5 +232,6 @@ private:
};
extern SPIFIFOclass SPIFIFO;

#endif
#endif // HAS_SPIFIFO

#endif

+ 23
- 98
teensy3/Tone.cpp View File

@@ -33,7 +33,6 @@
#include "HardwareSerial.h"
#include "IntervalTimer.h"

#if 1
// IntervalTimer based tone. This allows tone() to share the timers with other
// libraries, rather than permanently hogging one PIT timer even for projects
// which never use tone(). Someday this single-tone implementation might be
@@ -47,6 +46,19 @@ IntervalTimer tone_timer;

void tone_interrupt(void);

#if defined(KINETISK)
#define TONE_CLEAR_PIN tone_reg[0] = 1
#define TONE_TOGGLE_PIN tone_reg[128] = 1
#define TONE_OUTPUT_PIN tone_reg[384] = 1

#elif defined(KINETISL)
static uint8_t tone_mask;
#define TONE_CLEAR_PIN tone_reg[0] = tone_mask
#define TONE_TOGGLE_PIN tone_reg[4] = tone_mask
#define TONE_OUTPUT_PIN __disable_irq(); tone_reg[12] |= tone_mask; __enable_irq()

#endif

void tone(uint8_t pin, uint16_t frequency, uint32_t duration)
{
uint32_t count;
@@ -75,17 +87,20 @@ void tone(uint8_t pin, uint16_t frequency, uint32_t duration)
tone_toggle_count = count;
} else {
// same pin, but a new frequency.
tone_reg[0] = 1; // clear pin
TONE_CLEAR_PIN; // clear pin
tone_timer.begin(tone_interrupt, usec);
}
} else {
if (tone_pin < CORE_NUM_DIGITAL) {
tone_reg[0] = 1; // clear pin
TONE_CLEAR_PIN; // clear pin
}
tone_pin = pin;
tone_reg = portClearRegister(pin);
tone_reg[0] = 1; // clear pin
tone_reg[384] = 1; // output mode;
#if defined(KINETISL)
tone_mask = digitalPinToBitMask(pin);
#endif
TONE_CLEAR_PIN; // clear pin
TONE_OUTPUT_PIN; // output mode;
*config = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
tone_toggle_count = count;
tone_timer.begin(tone_interrupt, usec);
@@ -97,11 +112,11 @@ void tone(uint8_t pin, uint16_t frequency, uint32_t duration)
void tone_interrupt(void)
{
if (tone_toggle_count) {
tone_reg[128] = 1; // toggle
TONE_TOGGLE_PIN; // toggle
if (tone_toggle_count < 0xFFFFFFFF) tone_toggle_count--;
} else {
tone_timer.end();
tone_reg[0] = 0; // clear
TONE_CLEAR_PIN; // clear
tone_pin = 255;
tone_frequency = 0;
}
@@ -113,102 +128,12 @@ void noTone(uint8_t pin)
__disable_irq();
if (pin == tone_pin) {
tone_timer.end();
tone_reg[0] = 0; // clear
TONE_CLEAR_PIN; // clear
tone_pin = 255;
tone_frequency = 0;
}
__enable_irq();
}
#endif



#if 0
// Old PIT timer based tone(). This implementation is slightly more efficient,
// but it consumes one of the PIT timers, even for projects which never use tone().

static uint32_t tone_toggle_count;
static volatile uint8_t *tone_reg;
static uint8_t tone_pin;

void init_tone(void)
{
if (SIM_SCGC6 & SIM_SCGC6_PIT) return;
SIM_SCGC6 |= SIM_SCGC6_PIT; // TODO: use bitband for atomic read-mod-write
PIT_MCR = 0;
PIT_TCTRL3 = 0; // disabled
tone_pin = 255;
NVIC_ENABLE_IRQ(IRQ_PIT_CH3);
}

void tone(uint8_t pin, uint16_t frequency, uint32_t duration)
{
uint32_t count, load;
volatile uint32_t *config;

init_tone();
if (pin >= CORE_NUM_DIGITAL) return;
if (duration) {
count = (frequency * duration / 1000) * 2;
} else {
count = 0xFFFFFFFF;
}
load = (F_BUS / 2) / frequency;
config = portConfigRegister(pin);
__disable_irq();
if (pin != tone_pin) {
if (tone_pin < CORE_NUM_DIGITAL) {
tone_reg[0] = 1; // clear pin
}
tone_pin = pin;
tone_reg = portClearRegister(pin);
tone_reg[0] = 1; // clear pin
tone_reg[384] = 1; // output mode;
*config = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
}
tone_toggle_count = count;
if (PIT_LDVAL3 != load) {
PIT_TCTRL3 = 0;
PIT_LDVAL3 = load;
PIT_TCTRL3 = 3;
}
__enable_irq();
}

void pit3_isr(void)
{
PIT_TFLG3 = 1;

if (tone_toggle_count) {
tone_reg[128] = 1; // toggle
if (tone_toggle_count < 0xFFFFFFFF) tone_toggle_count--;
} else {
PIT_TCTRL3 = 0;
PIT_LDVAL3 = 0;
tone_reg[0] = 0; // clear
tone_pin = 255;
}
}

void noTone(uint8_t pin)
{
if (pin >= CORE_NUM_DIGITAL) return;
__disable_irq();
if (pin == tone_pin) {
PIT_TCTRL3 = 0;
PIT_LDVAL3 = 0;
tone_reg[0] = 0; // clear
tone_pin = 255;
}
__enable_irq();
}
#endif










+ 66
- 10
teensy3/analog.c View File

@@ -99,8 +99,10 @@ void analog_init(void)
{
uint32_t num;

#if defined(__MK20DX128__) || defined(__MK20DX256__)
VREF_TRM = 0x60;
VREF_SC = 0xE1; // enable 1.2 volt ref
#endif

if (analog_config_bits == 8) {
ADC0_CFG1 = ADC_CFG1_8BIT + ADC_CFG1_MODE(0);
@@ -132,17 +134,27 @@ void analog_init(void)
#endif
}

#if defined(__MK20DX128__)
if (analog_reference_internal) {
ADC0_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref
} else {
ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref
}
#elif defined(__MK20DX256__)
if (analog_reference_internal) {
ADC0_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref
#if defined(__MK20DX256__)
ADC1_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref
#endif
} else {
ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref
#if defined(__MK20DX256__)
ADC1_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref
#endif
}
#elif defined(__MKL26Z64__)
if (analog_reference_internal) {
ADC0_SC2 = ADC_SC2_REFSEL(0); // external AREF
} else {
ADC0_SC2 = ADC_SC2_REFSEL(1); // vcc
}
#endif

num = analog_num_average;
if (num <= 1) {
@@ -220,13 +232,19 @@ static void wait_for_cal(void)
// VREFH/VREFL - connected as the primary reference option
// 1.2 V VREF_OUT - connected as the VALT reference option

#if defined(__MK20DX128__) || defined(__MK20DX256__)
#define DEFAULT 0
#define INTERNAL 2
#define INTERNAL1V2 2
#define INTERNAL1V1 2
#define EXTERNAL 0

#elif defined(__MKL26Z64__)
#define DEFAULT 0
#define INTERNAL 0
#define EXTERNAL 1
#endif

void analogReference(uint8_t type)
{
if (type) {
@@ -321,6 +339,16 @@ static const uint8_t channel2sc1a[] = {
// A19 30 C11 ADC1_SE7b 7
// A20 31 E0 ADC1_SE4a 4+64
};
#elif defined(__MKL26Z64__)
static const uint8_t channel2sc1a[] = {
5, 14, 8, 9, 13, 12, 6, 7, 15, 11,
0, 4+64, 23
};





#endif


@@ -339,20 +367,40 @@ int analogRead(uint8_t pin)
//serial_phex(pin);
//serial_print(" ");

#if defined(__MK20DX128__)
if (pin <= 13) {
index = pin; // 0-13 refer to A0-A13
} else if (pin <= 23) {
index = pin - 14; // 14-23 are A0-A9
} else if (pin >= 34 && pin <= 40) {
index = pin - 24; // 34-37 are A10-A13, 38 is temp sensor,
// 39 is vref, 40 is unused analog pin
} else {
return 0;
}
#elif defined(__MK20DX256__)
if (pin <= 13) {
index = pin; // 0-13 refer to A0-A13
} else if (pin <= 23) {
index = pin - 14; // 14-23 are A0-A9
#if defined(__MK20DX256__)
} else if (pin >= 26 && pin <= 31) {
index = pin - 9; // 26-31 are A15-A20
#endif
} else if (pin >= 34 && pin <= 40) {
index = pin - 24; // 34-37 are A10-A13, 38 is temp sensor,
// 39 is vref, 40 is unused (A14 on Teensy 3.1)
index = pin - 24; // 34-37 are A10-A13, 38 is temp sensor,
// 39 is vref, 40 is A14
} else {
return 0; // all others are invalid
return 0;
}
#elif defined(__MKL26Z64__)
if (pin <= 12) {
index = pin; // 0-12 refer to A0-A12
} else if (pin >= 14 && pin <= 26) {
index = pin - 14; // 14-26 are A0-A12
} else {
return 0;
}

#endif

//serial_phex(index);
//serial_print(" ");
@@ -373,6 +421,14 @@ int analogRead(uint8_t pin)
__disable_irq();
startADC0:
//serial_print("startADC0\n");
#if defined(__MKL26Z64__)
if (channel & 0x40) {
ADC0_CFG2 &= ~ADC_CFG2_MUXSEL;
channel &= 0x3F;
} else {
ADC0_CFG2 |= ADC_CFG2_MUXSEL;
}
#endif
ADC0_SC1A = channel;
analogReadBusyADC0 = 1;
__enable_irq();

+ 329
- 42
teensy3/avr_emulation.h View File

@@ -38,10 +38,20 @@
#ifdef __cplusplus

#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000)
#define GPIO_BITBAND(reg, bit) (*(uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)))
#define CONFIG_PULLUP (PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS)
#define CONFIG_NOPULLUP (PORT_PCR_MUX(1))

#if defined(KINETISK)
// bitband addressing for atomic access to data direction register
#define GPIO_SETBIT_ATOMIC(reg, bit) (*(uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)) = 1)
#define GPIO_CLRBIT_ATOMIC(reg, bit) (*(uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)) = 0)
#elif defined(KINETISL)
// bit manipulation engine for atomic access to data direction register
#define GPIO_SETBIT_ATOMIC(reg, bit) (*(uint32_t *)(((uint32_t)&(reg) - 0xF8000000) | 0x480FF000) = 1 << (bit))
#define GPIO_CLRBIT_ATOMIC(reg, bit) (*(uint32_t *)(((uint32_t)&(reg) - 0xF8000000) | 0x440FF000) = ~(1 << (bit)))
#endif


class PORTDemulation
{
public:
@@ -213,76 +223,76 @@ public:
}
private:
inline void set0() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN0_DDRREG, CORE_PIN0_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN0_DDRREG, CORE_PIN0_BIT);
CORE_PIN0_CONFIG = CONFIG_PULLUP;
}
inline void set1() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN1_DDRREG, CORE_PIN1_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN1_DDRREG, CORE_PIN1_BIT);
CORE_PIN1_CONFIG = CONFIG_PULLUP;
}
inline void set2() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN2_DDRREG, CORE_PIN2_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN2_DDRREG, CORE_PIN2_BIT);
CORE_PIN2_CONFIG = CONFIG_PULLUP;
}
inline void set3() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN3_DDRREG, CORE_PIN3_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN3_DDRREG, CORE_PIN3_BIT);
CORE_PIN3_CONFIG = CONFIG_PULLUP;
}
inline void set4() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN4_DDRREG, CORE_PIN4_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN4_DDRREG, CORE_PIN4_BIT);
CORE_PIN4_CONFIG = CONFIG_PULLUP;
}
inline void set5() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN5_DDRREG, CORE_PIN5_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN5_DDRREG, CORE_PIN5_BIT);
CORE_PIN5_CONFIG = CONFIG_PULLUP;
}
inline void set6() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN6_DDRREG, CORE_PIN6_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN6_DDRREG, CORE_PIN6_BIT);
CORE_PIN6_CONFIG = CONFIG_PULLUP;
}
inline void set7() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN7_DDRREG, CORE_PIN7_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN7_DDRREG, CORE_PIN7_BIT);
CORE_PIN7_CONFIG = CONFIG_PULLUP;
}
inline void clr0() __attribute__((always_inline)) {
CORE_PIN0_CONFIG = ((CORE_PIN0_PORTREG & CORE_PIN0_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN0_DDRREG, CORE_PIN0_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN0_DDRREG, CORE_PIN0_BIT);
}
inline void clr1() __attribute__((always_inline)) {
CORE_PIN1_CONFIG = ((CORE_PIN1_PORTREG & CORE_PIN1_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN1_DDRREG, CORE_PIN1_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN1_DDRREG, CORE_PIN1_BIT);
}
inline void clr2() __attribute__((always_inline)) {
CORE_PIN2_CONFIG = ((CORE_PIN2_PORTREG & CORE_PIN2_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN2_DDRREG, CORE_PIN2_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN2_DDRREG, CORE_PIN2_BIT);
}
inline void clr3() __attribute__((always_inline)) {
CORE_PIN3_CONFIG = ((CORE_PIN3_PORTREG & CORE_PIN3_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN3_DDRREG, CORE_PIN3_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN3_DDRREG, CORE_PIN3_BIT);
}
inline void clr4() __attribute__((always_inline)) {
CORE_PIN4_CONFIG = ((CORE_PIN4_PORTREG & CORE_PIN4_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN4_DDRREG, CORE_PIN4_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN4_DDRREG, CORE_PIN4_BIT);
}
inline void clr5() __attribute__((always_inline)) {
CORE_PIN5_CONFIG = ((CORE_PIN5_PORTREG & CORE_PIN5_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN5_DDRREG, CORE_PIN5_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN5_DDRREG, CORE_PIN5_BIT);
}
inline void clr6() __attribute__((always_inline)) {
CORE_PIN6_CONFIG = ((CORE_PIN6_PORTREG & CORE_PIN6_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN6_DDRREG, CORE_PIN6_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN6_DDRREG, CORE_PIN6_BIT);
}
inline void clr7() __attribute__((always_inline)) {
CORE_PIN7_CONFIG = ((CORE_PIN7_PORTREG & CORE_PIN7_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN7_DDRREG, CORE_PIN7_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN7_DDRREG, CORE_PIN7_BIT);
}
};

@@ -432,58 +442,58 @@ public:
}
private:
inline void set0() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN8_DDRREG, CORE_PIN8_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN8_DDRREG, CORE_PIN8_BIT);
CORE_PIN8_CONFIG = CONFIG_PULLUP;
}
inline void set1() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN9_DDRREG, CORE_PIN9_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN9_DDRREG, CORE_PIN9_BIT);
CORE_PIN9_CONFIG = CONFIG_PULLUP;
}
inline void set2() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN10_DDRREG, CORE_PIN10_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN10_DDRREG, CORE_PIN10_BIT);
CORE_PIN10_CONFIG = CONFIG_PULLUP;
}
inline void set3() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN11_DDRREG, CORE_PIN11_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN11_DDRREG, CORE_PIN11_BIT);
CORE_PIN11_CONFIG = CONFIG_PULLUP;
}
inline void set4() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN12_DDRREG, CORE_PIN12_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN12_DDRREG, CORE_PIN12_BIT);
CORE_PIN12_CONFIG = CONFIG_PULLUP;
}
inline void set5() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN13_DDRREG, CORE_PIN13_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN13_DDRREG, CORE_PIN13_BIT);
CORE_PIN13_CONFIG = CONFIG_PULLUP;
}
inline void clr0() __attribute__((always_inline)) {
CORE_PIN8_CONFIG = ((CORE_PIN8_PORTREG & CORE_PIN8_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN8_DDRREG, CORE_PIN8_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN8_DDRREG, CORE_PIN8_BIT);
}
inline void clr1() __attribute__((always_inline)) {
CORE_PIN9_CONFIG = ((CORE_PIN9_PORTREG & CORE_PIN9_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN9_DDRREG, CORE_PIN9_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN9_DDRREG, CORE_PIN9_BIT);
}
inline void clr2() __attribute__((always_inline)) {
CORE_PIN10_CONFIG = ((CORE_PIN10_PORTREG & CORE_PIN10_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN10_DDRREG, CORE_PIN10_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN10_DDRREG, CORE_PIN10_BIT);
}
inline void clr3() __attribute__((always_inline)) {
CORE_PIN11_CONFIG = ((CORE_PIN11_PORTREG & CORE_PIN11_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN11_DDRREG, CORE_PIN11_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN11_DDRREG, CORE_PIN11_BIT);
}
inline void clr4() __attribute__((always_inline)) {
CORE_PIN12_CONFIG = ((CORE_PIN12_PORTREG & CORE_PIN12_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN12_DDRREG, CORE_PIN12_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN12_DDRREG, CORE_PIN12_BIT);
}
inline void clr5() __attribute__((always_inline)) {
CORE_PIN13_CONFIG = ((CORE_PIN13_PORTREG & CORE_PIN13_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN13_DDRREG, CORE_PIN13_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN13_DDRREG, CORE_PIN13_BIT);
}
};

@@ -633,58 +643,58 @@ public:
}
private:
inline void set0() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN14_DDRREG, CORE_PIN14_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN14_DDRREG, CORE_PIN14_BIT);
CORE_PIN14_CONFIG = CONFIG_PULLUP;
}
inline void set1() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN15_DDRREG, CORE_PIN15_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN15_DDRREG, CORE_PIN15_BIT);
CORE_PIN15_CONFIG = CONFIG_PULLUP;
}
inline void set2() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN16_DDRREG, CORE_PIN16_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN16_DDRREG, CORE_PIN16_BIT);
CORE_PIN16_CONFIG = CONFIG_PULLUP;
}
inline void set3() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN17_DDRREG, CORE_PIN17_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN17_DDRREG, CORE_PIN17_BIT);
CORE_PIN17_CONFIG = CONFIG_PULLUP;
}
inline void set4() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN18_DDRREG, CORE_PIN18_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN18_DDRREG, CORE_PIN18_BIT);
CORE_PIN18_CONFIG = CONFIG_PULLUP;
}
inline void set5() __attribute__((always_inline)) {
GPIO_BITBAND(CORE_PIN19_DDRREG, CORE_PIN19_BIT) = 1;
GPIO_SETBIT_ATOMIC(CORE_PIN19_DDRREG, CORE_PIN19_BIT);
CORE_PIN19_CONFIG = CONFIG_PULLUP;
}
inline void clr0() __attribute__((always_inline)) {
CORE_PIN14_CONFIG = ((CORE_PIN14_PORTREG & CORE_PIN14_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN14_DDRREG, CORE_PIN14_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN14_DDRREG, CORE_PIN14_BIT);
}
inline void clr1() __attribute__((always_inline)) {
CORE_PIN15_CONFIG = ((CORE_PIN15_PORTREG & CORE_PIN15_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN15_DDRREG, CORE_PIN15_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN15_DDRREG, CORE_PIN15_BIT);
}
inline void clr2() __attribute__((always_inline)) {
CORE_PIN16_CONFIG = ((CORE_PIN16_PORTREG & CORE_PIN16_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN16_DDRREG, CORE_PIN16_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN16_DDRREG, CORE_PIN16_BIT);
}
inline void clr3() __attribute__((always_inline)) {
CORE_PIN17_CONFIG = ((CORE_PIN17_PORTREG & CORE_PIN17_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN17_DDRREG, CORE_PIN17_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN17_DDRREG, CORE_PIN17_BIT);
}
inline void clr4() __attribute__((always_inline)) {
CORE_PIN18_CONFIG = ((CORE_PIN18_PORTREG & CORE_PIN18_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN18_DDRREG, CORE_PIN18_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN18_DDRREG, CORE_PIN18_BIT);
}
inline void clr5() __attribute__((always_inline)) {
CORE_PIN19_CONFIG = ((CORE_PIN19_PORTREG & CORE_PIN19_BITMASK)
? CONFIG_PULLUP : CONFIG_NOPULLUP);
GPIO_BITBAND(CORE_PIN19_DDRREG, CORE_PIN19_BIT) = 0;
GPIO_CLRBIT_ATOMIC(CORE_PIN19_DDRREG, CORE_PIN19_BIT);
}
};

@@ -790,10 +800,13 @@ void serial_phex32(uint32_t n);
#define SPI2X 0 // SPI2X: Double SPI Speed Bit
// SPI Data Register ­ SPDR


class SPCRemulation;
class SPSRemulation;
class SPDRemulation;

#if defined(KINETISK)

class SPCRemulation
{
public:
@@ -1122,6 +1135,246 @@ public:
extern SPDRemulation SPDR;





#elif defined(KINETISL)

// SPI Control Register ­ SPCR
//#define SPIE 7 // SPI Interrupt Enable - not supported
//#define SPE 6 // SPI Enable
//#define DORD 5 // DORD: Data Order
//#define MSTR 4 // MSTR: Master/Slave Select
//#define CPOL 3 // CPOL: Clock Polarity
//#define CPHA 2 // CPHA: Clock Phase
//#define SPR1 1 // Clock: 3 = 125 kHz, 2 = 250 kHz, 1 = 1 MHz, 0->4 MHz
//#define SPR0 0
// SPI Status Register ­ SPSR
//#define SPIF 7 // SPIF: SPI Interrupt Flag
//#define WCOL 6 // WCOL: Write COLlision Flag - not implemented
//#define SPI2X 0 // SPI2X: Double SPI Speed Bit
// SPI Data Register ­ SPDR


class SPCRemulation
{
public:
inline SPCRemulation & operator = (int val) __attribute__((always_inline)) {
uint32_t sim4 = SIM_SCGC4;
if (!(sim4 & SIM_SCGC4_SPI0)) {
SIM_SCGC4 = sim4 | SIM_SCGC4_SPI0;
SPI0_BR = SPI_BR_SPR(0) | SPI_BR_SPPR(1);
}
uint32_t c1 = 0;
if (val & (1<<DORD)) c1 |= SPI_C1_LSBFE;
if (val & (1<<CPOL)) c1 |= SPI_C1_CPOL;
if (val & (1<<CPHA)) c1 |= SPI_C1_CPHA;
if (val & (1<<MSTR)) c1 |= SPI_C1_MSTR;
if (val & (1<<SPE)) c1 |= SPI_C1_SPE;
SPI0_C1 = c1;
SPI0_C2 = 0;
uint32_t br = SPI0_BR & 0x10;
switch (val & 3) {
case 0: SPI0_BR = br | SPI_BR_SPR(0); break;
case 1: SPI0_BR = br | SPI_BR_SPR(2); break;
case 2: SPI0_BR = br | SPI_BR_SPR(4); break;
default: SPI0_BR = br | SPI_BR_SPR(5); break;
}
if (val & (1<<SPE)) enable_pins();
else disable_pins();
return *this;
}
inline SPCRemulation & operator |= (int val) __attribute__((always_inline)) {
uint32_t sim4 = SIM_SCGC4;
if (!(sim4 & SIM_SCGC4_SPI0)) {
SIM_SCGC4 = sim4 | SIM_SCGC4_SPI0;
SPI0_BR = SPI_BR_SPR(0) | SPI_BR_SPPR(1);
}
uint32_t c1 = SPI0_C1;
if (val & (1<<DORD)) c1 |= SPI_C1_LSBFE;
if (val & (1<<CPOL)) c1 |= SPI_C1_CPOL;
if (val & (1<<CPHA)) c1 |= SPI_C1_CPHA;
if (val & (1<<MSTR)) c1 |= SPI_C1_MSTR;
if (val & (1<<SPE)) {
enable_pins();
c1 |= SPI_C1_SPE;
}
SPI0_C1 = c1;
SPI0_C2 = 0;
val &= 3;
if (val) {
uint32_t br = SPI0_BR;
uint32_t bits = baud2avr(br) | val;
br &= 0x10;
switch (bits) {
case 0: SPI0_BR = br | SPI_BR_SPR(0); break;
case 1: SPI0_BR = br | SPI_BR_SPR(2); break;
case 2: SPI0_BR = br | SPI_BR_SPR(4); break;
default: SPI0_BR = br | SPI_BR_SPR(5); break;
}
}
return *this;
}
inline SPCRemulation & operator &= (int val) __attribute__((always_inline)) {
uint32_t sim4 = SIM_SCGC4;
if (!(sim4 & SIM_SCGC4_SPI0)) {
SIM_SCGC4 = sim4 | SIM_SCGC4_SPI0;
SPI0_BR = SPI_BR_SPR(0) | SPI_BR_SPPR(1);
}
uint32_t c1 = SPI0_C1;
if (!(val & (1<<DORD))) c1 &= ~SPI_C1_LSBFE;
if (!(val & (1<<CPOL))) c1 &= ~SPI_C1_CPOL;
if (!(val & (1<<CPHA))) c1 &= ~SPI_C1_CPHA;
if (!(val & (1<<MSTR))) c1 &= ~SPI_C1_MSTR;
if (!(val & (1<<SPE))) {
disable_pins();
c1 &= ~SPI_C1_SPE;
}
SPI0_C1 = c1;
SPI0_C2 = 0;
val &= 3;
if (val < 3) {
uint32_t br = SPI0_BR;
uint32_t bits = baud2avr(br) & val;
br &= 0x10;
switch (bits) {
case 0: SPI0_BR = br | SPI_BR_SPR(0); break;
case 1: SPI0_BR = br | SPI_BR_SPR(2); break;
case 2: SPI0_BR = br | SPI_BR_SPR(4); break;
default: SPI0_BR = br | SPI_BR_SPR(5); break;
}
}
return *this;
}
inline int operator & (int val) const __attribute__((always_inline)) {
int ret = 0;
uint32_t sim4 = SIM_SCGC4;
if (!(sim4 & SIM_SCGC4_SPI0)) {
SIM_SCGC4 = sim4 | SIM_SCGC4_SPI0;
SPI0_BR = SPI_BR_SPR(0) | SPI_BR_SPPR(1);
}
uint32_t c1 = SPI0_C1;
if ((val & (1<<DORD)) && (c1 & SPI_C1_LSBFE)) ret |= (1<<DORD);
if ((val & (1<<CPOL)) && (c1 & SPI_C1_CPOL)) ret |= (1<<CPOL);
if ((val & (1<<CPHA)) && (c1 & SPI_C1_CPHA)) ret |= (1<<CPHA);
if ((val & (1<<MSTR)) && (c1 & SPI_C1_MSTR)) ret |= (1<<MSTR);
if ((val & (1<<SPE)) && (c1 & SPI_C1_SPE)) ret |= (1<<SPE);
uint32_t bits = baud2avr(SPI0_BR);
if ((val & (1<<SPR1)) && (bits & (1<<SPR1))) ret |= (1<<SPR1);
if ((val & (1<<SPR0)) && (bits & (1<<SPR0))) ret |= (1<<SPR0);
return ret;
}
operator int () const __attribute__((always_inline)) {
int ret = 0;
uint32_t sim4 = SIM_SCGC4;
if (!(sim4 & SIM_SCGC4_SPI0)) {
SIM_SCGC4 = sim4 | SIM_SCGC4_SPI0;
SPI0_BR = SPI_BR_SPR(0) | SPI_BR_SPPR(1);
}
uint32_t c1 = SPI0_C1;
if ((c1 & SPI_C1_LSBFE)) ret |= (1<<DORD);
if ((c1 & SPI_C1_CPOL)) ret |= (1<<CPOL);
if ((c1 & SPI_C1_CPHA)) ret |= (1<<CPHA);
if ((c1 & SPI_C1_MSTR)) ret |= (1<<MSTR);
if ((c1 & SPI_C1_SPE)) ret |= (1<<SPE);
ret |= baud2avr(SPI0_BR);
return ret;
}
inline void setMOSI(uint8_t pin) __attribute__((always_inline)) {
}
inline void setMISO(uint8_t pin) __attribute__((always_inline)) {
}
inline void setSCK(uint8_t pin) __attribute__((always_inline)) {
}
friend class SPSRemulation;
friend class SPIFIFOclass;
private:
static inline uint32_t baud2avr(uint32_t br) __attribute__((always_inline)) {
br &= 15;
if (br == 0) return 0;
if (br <= 2) return 1;
if (br <= 4) return 2;
return 3;
}
static uint8_t pinout;
public:
inline void enable_pins(void) __attribute__((always_inline)) {
//serial_print("enable_pins\n");
CORE_PIN11_CONFIG = PORT_PCR_MUX(2); // MOSI = 11 (PTC6)
CORE_PIN12_CONFIG = PORT_PCR_MUX(2); // MISO = 12 (PTC7)
CORE_PIN13_CONFIG = PORT_PCR_MUX(2); // SCK = 13 (PTC5)
}
inline void disable_pins(void) __attribute__((always_inline)) {
//serial_print("disable_pins\n");
CORE_PIN11_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1);
CORE_PIN12_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1);
CORE_PIN13_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1);
}
};
extern SPCRemulation SPCR;


class SPSRemulation
{
public:
inline SPSRemulation & operator = (int val) __attribute__((always_inline)) {
if (val & (1<<SPI2X)) {
SPI0_BR &= ~0x10;
} else {
SPI0_BR |= 0x10;
}
return *this;
}
inline SPSRemulation & operator |= (int val) __attribute__((always_inline)) {
if (val & (1<<SPI2X)) SPI0_BR &= ~0x10;
return *this;
}
inline SPSRemulation & operator &= (int val) __attribute__((always_inline)) {
if (!(val & (1<<SPI2X))) SPI0_BR |= 0x10;
return *this;
}
inline int operator & (int val) const __attribute__((always_inline)) {
int ret = 0;
if ((val & (1<<SPIF)) && (SPI0_S & SPI_S_SPRF)) ret = (1<<SPIF);
if ((val & (1<<SPI2X)) && (!(SPI0_BR & 0x10))) ret |= (1<<SPI2X);
return ret;
}
operator int () const __attribute__((always_inline)) {
int ret = 0;
if ((SPI0_S & SPI_S_SPRF)) ret = (1<<SPIF);
if (!(SPI0_BR & 0x10)) ret |= (1<<SPI2X);
return ret;
}
};
extern SPSRemulation SPSR;


class SPDRemulation
{
public:
inline SPDRemulation & operator = (int val) __attribute__((always_inline)) {
if ((SPI0_S & SPI_S_SPTEF)) {
uint32_t tmp __attribute__((unused)) = SPI0_DL;
}
SPI0_DL = val;
return *this;
}
operator int () const __attribute__((always_inline)) {
return SPI0_DL & 255;
}
};
extern SPDRemulation SPDR;


#endif // KINETISK








class SREGemulation
{
public:
@@ -1147,6 +1400,7 @@ extern SREGemulation SREG;
// 84062840
// 322111
// 17395173
#if defined(__MK20DX128__) || defined(__MK20DX256__)
#define EIMSK_pA 0x01000018 // pins 3, 4, 24
#define EIMSK_pB 0x020F0003 // pins 0, 1, 16-19, 25
#define EIMSK_pC 0x78C0BE00 // pins 9-13, 15, 22, 23, 27-30
@@ -1186,12 +1440,45 @@ public:
};
extern EIMSKemulation EIMSK;

#elif defined(__MKL26Z64__)

#define EIMSK_pA 0x00000018 // pins 3, 4, 24
#define EIMSK_pC 0x00C0BE00 // pins 9-13, 15, 22, 23
#define EIMSK_pD 0x003041E4 // pins 2, 5-8, 14, 20, 21

class EIMSKemulation // used by Adafruit_nRF8001
{
public:
operator int () const __attribute__((always_inline)) {
int mask = 0;
volatile const uint32_t *icer = &NVIC_ICER0;
if (icer[IRQ_PORTA >> 5] & (1 << (IRQ_PORTA & 31))) mask |= EIMSK_pA;
if (icer[IRQ_PORTCD >> 5] & (1 << (IRQ_PORTCD & 31))) mask |= (EIMSK_pC | EIMSK_pD);
return mask;
}
inline EIMSKemulation & operator |= (int val) __attribute__((always_inline)) {
if (val & EIMSK_pA) NVIC_ENABLE_IRQ(IRQ_PORTA);
if (val & (EIMSK_pC | EIMSK_pD)) NVIC_ENABLE_IRQ(IRQ_PORTCD);
return *this;
}
inline EIMSKemulation & operator &= (int val) __attribute__((always_inline)) {
uint32_t n = val;
if ((n | ~EIMSK_pA) != 0xFFFFFFFF) NVIC_DISABLE_IRQ(IRQ_PORTA);
if ((n | ~(EIMSK_pC | EIMSK_pD)) != 0xFFFFFFFF) NVIC_DISABLE_IRQ(IRQ_PORTCD);
return *this;
}
};
extern EIMSKemulation EIMSK;

#endif


// these are not intended for public consumption...
#undef GPIO_BITBAND_ADDR
#undef GPIO_BITBAND
#undef CONFIG_PULLUP
#undef CONFIG_NOPULLUP
#undef GPIO_SETBIT_ATOMIC
#undef GPIO_CLRBIT_ATOMIC

#endif // __cplusplus


+ 315
- 7
teensy3/core_pins.h View File

@@ -93,17 +93,28 @@
// A2 FTM0_CH7 SWD Trace
// A3 FTM0_CH0 SWD Data

#if defined(__MK20DX128__)
#define CORE_NUM_TOTAL_PINS 34
#define CORE_NUM_DIGITAL 34
#define CORE_NUM_INTERRUPT 34
#if defined(__MK20DX128__)
#define CORE_NUM_ANALOG 14
#define CORE_NUM_PWM 10
#elif defined(__MK20DX256__)
#define CORE_NUM_TOTAL_PINS 34
#define CORE_NUM_DIGITAL 34
#define CORE_NUM_INTERRUPT 34
#define CORE_NUM_ANALOG 21
#define CORE_NUM_PWM 12
#elif defined(__MKL26Z64__)
#define CORE_NUM_TOTAL_PINS 27
#define CORE_NUM_DIGITAL 27
#define CORE_NUM_INTERRUPT 18
#define CORE_NUM_ANALOG 13
#define CORE_NUM_PWM 10
#endif

#if defined(__MK20DX128__) || defined(__MK20DX256__)

#define CORE_PIN0_BIT 16
#define CORE_PIN1_BIT 17
#define CORE_PIN2_BIT 0
@@ -443,6 +454,276 @@
#define CORE_INT_EVERY_PIN 1


#elif defined(__MKL26Z64__)

#define CORE_PIN0_BIT 16
#define CORE_PIN1_BIT 17
#define CORE_PIN2_BIT 0
#define CORE_PIN3_BIT 1
#define CORE_PIN4_BIT 2
#define CORE_PIN5_BIT 7
#define CORE_PIN6_BIT 4
#define CORE_PIN7_BIT 2
#define CORE_PIN8_BIT 3
#define CORE_PIN9_BIT 3
#define CORE_PIN10_BIT 4
#define CORE_PIN11_BIT 6
#define CORE_PIN12_BIT 7
#define CORE_PIN13_BIT 5
#define CORE_PIN14_BIT 1
#define CORE_PIN15_BIT 0
#define CORE_PIN16_BIT 0
#define CORE_PIN17_BIT 1
#define CORE_PIN18_BIT 3
#define CORE_PIN19_BIT 2
#define CORE_PIN20_BIT 5
#define CORE_PIN21_BIT 6
#define CORE_PIN22_BIT 1
#define CORE_PIN23_BIT 2
#define CORE_PIN24_BIT 20
#define CORE_PIN25_BIT 21
#define CORE_PIN26_BIT 30

#define CORE_PIN0_BITMASK (1<<(CORE_PIN0_BIT))
#define CORE_PIN1_BITMASK (1<<(CORE_PIN1_BIT))
#define CORE_PIN2_BITMASK (1<<(CORE_PIN2_BIT))
#define CORE_PIN3_BITMASK (1<<(CORE_PIN3_BIT))
#define CORE_PIN4_BITMASK (1<<(CORE_PIN4_BIT))
#define CORE_PIN5_BITMASK (1<<(CORE_PIN5_BIT))
#define CORE_PIN6_BITMASK (1<<(CORE_PIN6_BIT))
#define CORE_PIN7_BITMASK (1<<(CORE_PIN7_BIT))
#define CORE_PIN8_BITMASK (1<<(CORE_PIN8_BIT))
#define CORE_PIN9_BITMASK (1<<(CORE_PIN9_BIT))
#define CORE_PIN10_BITMASK (1<<(CORE_PIN10_BIT))
#define CORE_PIN11_BITMASK (1<<(CORE_PIN11_BIT))
#define CORE_PIN12_BITMASK (1<<(CORE_PIN12_BIT))
#define CORE_PIN13_BITMASK (1<<(CORE_PIN13_BIT))
#define CORE_PIN14_BITMASK (1<<(CORE_PIN14_BIT))
#define CORE_PIN15_BITMASK (1<<(CORE_PIN15_BIT))
#define CORE_PIN16_BITMASK (1<<(CORE_PIN16_BIT))
#define CORE_PIN17_BITMASK (1<<(CORE_PIN17_BIT))
#define CORE_PIN18_BITMASK (1<<(CORE_PIN18_BIT))
#define CORE_PIN19_BITMASK (1<<(CORE_PIN19_BIT))
#define CORE_PIN20_BITMASK (1<<(CORE_PIN20_BIT))
#define CORE_PIN21_BITMASK (1<<(CORE_PIN21_BIT))
#define CORE_PIN22_BITMASK (1<<(CORE_PIN22_BIT))
#define CORE_PIN23_BITMASK (1<<(CORE_PIN23_BIT))
#define CORE_PIN24_BITMASK (1<<(CORE_PIN24_BIT))
#define CORE_PIN25_BITMASK (1<<(CORE_PIN25_BIT))
#define CORE_PIN26_BITMASK (1<<(CORE_PIN26_BIT))

#define CORE_PIN0_PORTREG FGPIOB_PDOR
#define CORE_PIN1_PORTREG FGPIOB_PDOR
#define CORE_PIN2_PORTREG FGPIOD_PDOR
#define CORE_PIN3_PORTREG FGPIOA_PDOR
#define CORE_PIN4_PORTREG FGPIOA_PDOR
#define CORE_PIN5_PORTREG FGPIOD_PDOR
#define CORE_PIN6_PORTREG FGPIOD_PDOR
#define CORE_PIN7_PORTREG FGPIOD_PDOR
#define CORE_PIN8_PORTREG FGPIOD_PDOR
#define CORE_PIN9_PORTREG FGPIOC_PDOR
#define CORE_PIN10_PORTREG FGPIOC_PDOR
#define CORE_PIN11_PORTREG FGPIOC_PDOR
#define CORE_PIN12_PORTREG FGPIOC_PDOR
#define CORE_PIN13_PORTREG FGPIOC_PDOR
#define CORE_PIN14_PORTREG FGPIOD_PDOR
#define CORE_PIN15_PORTREG FGPIOC_PDOR
#define CORE_PIN16_PORTREG FGPIOB_PDOR
#define CORE_PIN17_PORTREG FGPIOB_PDOR
#define CORE_PIN18_PORTREG FGPIOB_PDOR
#define CORE_PIN19_PORTREG FGPIOB_PDOR
#define CORE_PIN20_PORTREG FGPIOD_PDOR
#define CORE_PIN21_PORTREG FGPIOD_PDOR
#define CORE_PIN22_PORTREG FGPIOC_PDOR
#define CORE_PIN23_PORTREG FGPIOC_PDOR
#define CORE_PIN24_PORTREG FGPIOE_PDOR
#define CORE_PIN25_PORTREG FGPIOE_PDOR
#define CORE_PIN26_PORTREG FGPIOE_PDOR

#define CORE_PIN0_PORTSET FGPIOB_PSOR
#define CORE_PIN1_PORTSET FGPIOB_PSOR
#define CORE_PIN2_PORTSET FGPIOD_PSOR
#define CORE_PIN3_PORTSET FGPIOA_PSOR
#define CORE_PIN4_PORTSET FGPIOA_PSOR
#define CORE_PIN5_PORTSET FGPIOD_PSOR
#define CORE_PIN6_PORTSET FGPIOD_PSOR
#define CORE_PIN7_PORTSET FGPIOD_PSOR
#define CORE_PIN8_PORTSET FGPIOD_PSOR
#define CORE_PIN9_PORTSET FGPIOC_PSOR
#define CORE_PIN10_PORTSET FGPIOC_PSOR
#define CORE_PIN11_PORTSET FGPIOC_PSOR
#define CORE_PIN12_PORTSET FGPIOC_PSOR
#define CORE_PIN13_PORTSET FGPIOC_PSOR
#define CORE_PIN14_PORTSET FGPIOD_PSOR
#define CORE_PIN15_PORTSET FGPIOC_PSOR
#define CORE_PIN16_PORTSET FGPIOB_PSOR
#define CORE_PIN17_PORTSET FGPIOB_PSOR
#define CORE_PIN18_PORTSET FGPIOB_PSOR
#define CORE_PIN19_PORTSET FGPIOB_PSOR
#define CORE_PIN20_PORTSET FGPIOD_PSOR
#define CORE_PIN21_PORTSET FGPIOD_PSOR
#define CORE_PIN22_PORTSET FGPIOC_PSOR
#define CORE_PIN23_PORTSET FGPIOC_PSOR
#define CORE_PIN24_PORTSET FGPIOE_PSOR
#define CORE_PIN25_PORTSET FGPIOE_PSOR
#define CORE_PIN26_PORTSET FGPIOE_PSOR

#define CORE_PIN0_PORTCLEAR FGPIOB_PCOR
#define CORE_PIN1_PORTCLEAR FGPIOB_PCOR
#define CORE_PIN2_PORTCLEAR FGPIOD_PCOR
#define CORE_PIN3_PORTCLEAR FGPIOA_PCOR
#define CORE_PIN4_PORTCLEAR FGPIOA_PCOR
#define CORE_PIN5_PORTCLEAR FGPIOD_PCOR
#define CORE_PIN6_PORTCLEAR FGPIOD_PCOR
#define CORE_PIN7_PORTCLEAR FGPIOD_PCOR
#define CORE_PIN8_PORTCLEAR FGPIOD_PCOR
#define CORE_PIN9_PORTCLEAR FGPIOC_PCOR
#define CORE_PIN10_PORTCLEAR FGPIOC_PCOR
#define CORE_PIN11_PORTCLEAR FGPIOC_PCOR
#define CORE_PIN12_PORTCLEAR FGPIOC_PCOR
#define CORE_PIN13_PORTCLEAR FGPIOC_PCOR
#define CORE_PIN14_PORTCLEAR FGPIOD_PCOR
#define CORE_PIN15_PORTCLEAR FGPIOC_PCOR
#define CORE_PIN16_PORTCLEAR FGPIOB_PCOR
#define CORE_PIN17_PORTCLEAR FGPIOB_PCOR
#define CORE_PIN18_PORTCLEAR FGPIOB_PCOR
#define CORE_PIN19_PORTCLEAR FGPIOB_PCOR
#define CORE_PIN20_PORTCLEAR FGPIOD_PCOR
#define CORE_PIN21_PORTCLEAR FGPIOD_PCOR
#define CORE_PIN22_PORTCLEAR FGPIOC_PCOR
#define CORE_PIN23_PORTCLEAR FGPIOC_PCOR
#define CORE_PIN24_PORTCLEAR FGPIOE_PCOR
#define CORE_PIN25_PORTCLEAR FGPIOE_PCOR
#define CORE_PIN26_PORTCLEAR FGPIOE_PCOR

#define CORE_PIN0_DDRREG FGPIOB_PDDR
#define CORE_PIN1_DDRREG FGPIOB_PDDR
#define CORE_PIN2_DDRREG FGPIOD_PDDR
#define CORE_PIN3_DDRREG FGPIOA_PDDR
#define CORE_PIN4_DDRREG FGPIOA_PDDR
#define CORE_PIN5_DDRREG FGPIOD_PDDR
#define CORE_PIN6_DDRREG FGPIOD_PDDR
#define CORE_PIN7_DDRREG FGPIOD_PDDR
#define CORE_PIN8_DDRREG FGPIOD_PDDR
#define CORE_PIN9_DDRREG FGPIOC_PDDR
#define CORE_PIN10_DDRREG FGPIOC_PDDR
#define CORE_PIN11_DDRREG FGPIOC_PDDR
#define CORE_PIN12_DDRREG FGPIOC_PDDR
#define CORE_PIN13_DDRREG FGPIOC_PDDR
#define CORE_PIN14_DDRREG FGPIOD_PDDR
#define CORE_PIN15_DDRREG FGPIOC_PDDR
#define CORE_PIN16_DDRREG FGPIOB_PDDR
#define CORE_PIN17_DDRREG FGPIOB_PDDR
#define CORE_PIN18_DDRREG FGPIOB_PDDR
#define CORE_PIN19_DDRREG FGPIOB_PDDR
#define CORE_PIN20_DDRREG FGPIOD_PDDR
#define CORE_PIN21_DDRREG FGPIOD_PDDR
#define CORE_PIN22_DDRREG FGPIOC_PDDR
#define CORE_PIN23_DDRREG FGPIOC_PDDR
#define CORE_PIN24_DDRREG FGPIOE_PDDR
#define CORE_PIN25_DDRREG FGPIOE_PDDR
#define CORE_PIN26_DDRREG FGPIOE_PDDR

#define CORE_PIN0_PINREG FGPIOB_PDIR
#define CORE_PIN1_PINREG FGPIOB_PDIR
#define CORE_PIN2_PINREG FGPIOD_PDIR
#define CORE_PIN3_PINREG FGPIOA_PDIR
#define CORE_PIN4_PINREG FGPIOA_PDIR
#define CORE_PIN5_PINREG FGPIOD_PDIR
#define CORE_PIN6_PINREG FGPIOD_PDIR
#define CORE_PIN7_PINREG FGPIOD_PDIR
#define CORE_PIN8_PINREG FGPIOD_PDIR
#define CORE_PIN9_PINREG FGPIOC_PDIR
#define CORE_PIN10_PINREG FGPIOC_PDIR
#define CORE_PIN11_PINREG FGPIOC_PDIR
#define CORE_PIN12_PINREG FGPIOC_PDIR
#define CORE_PIN13_PINREG FGPIOC_PDIR
#define CORE_PIN14_PINREG FGPIOD_PDIR
#define CORE_PIN15_PINREG FGPIOC_PDIR
#define CORE_PIN16_PINREG FGPIOB_PDIR
#define CORE_PIN17_PINREG FGPIOB_PDIR
#define CORE_PIN18_PINREG FGPIOB_PDIR
#define CORE_PIN19_PINREG FGPIOB_PDIR
#define CORE_PIN20_PINREG FGPIOD_PDIR
#define CORE_PIN21_PINREG FGPIOD_PDIR
#define CORE_PIN22_PINREG FGPIOC_PDIR
#define CORE_PIN23_PINREG FGPIOC_PDIR
#define CORE_PIN24_PINREG FGPIOE_PDIR
#define CORE_PIN25_PINREG FGPIOE_PDIR
#define CORE_PIN26_PINREG FGPIOE_PDIR

#define CORE_PIN0_CONFIG PORTB_PCR16
#define CORE_PIN1_CONFIG PORTB_PCR17
#define CORE_PIN2_CONFIG PORTD_PCR0
#define CORE_PIN3_CONFIG PORTA_PCR1
#define CORE_PIN4_CONFIG PORTA_PCR2
#define CORE_PIN5_CONFIG PORTD_PCR7
#define CORE_PIN6_CONFIG PORTD_PCR4
#define CORE_PIN7_CONFIG PORTD_PCR2
#define CORE_PIN8_CONFIG PORTD_PCR3
#define CORE_PIN9_CONFIG PORTC_PCR3
#define CORE_PIN10_CONFIG PORTC_PCR4
#define CORE_PIN11_CONFIG PORTC_PCR6
#define CORE_PIN12_CONFIG PORTC_PCR7
#define CORE_PIN13_CONFIG PORTC_PCR5
#define CORE_PIN14_CONFIG PORTD_PCR1
#define CORE_PIN15_CONFIG PORTC_PCR0
#define CORE_PIN16_CONFIG PORTB_PCR0
#define CORE_PIN17_CONFIG PORTB_PCR1
#define CORE_PIN18_CONFIG PORTB_PCR3
#define CORE_PIN19_CONFIG PORTB_PCR2
#define CORE_PIN20_CONFIG PORTD_PCR5
#define CORE_PIN21_CONFIG PORTD_PCR6
#define CORE_PIN22_CONFIG PORTC_PCR1
#define CORE_PIN23_CONFIG PORTC_PCR2
#define CORE_PIN24_CONFIG PORTE_PCR20
#define CORE_PIN25_CONFIG PORTE_PCR21
#define CORE_PIN26_CONFIG PORTE_PCR30

#define CORE_ADC0_PIN 14
#define CORE_ADC1_PIN 15
#define CORE_ADC2_PIN 16
#define CORE_ADC3_PIN 17
#define CORE_ADC4_PIN 18
#define CORE_ADC5_PIN 19
#define CORE_ADC6_PIN 20
#define CORE_ADC7_PIN 21
#define CORE_ADC8_PIN 22
#define CORE_ADC9_PIN 23
#define CORE_ADC10_PIN 24
#define CORE_ADC11_PIN 25
#define CORE_ADC12_PIN 26

#define CORE_RXD0_PIN 0
#define CORE_TXD0_PIN 1
#define CORE_RXD1_PIN 9
#define CORE_TXD1_PIN 10
#define CORE_RXD2_PIN 7
#define CORE_TXD2_PIN 8

#define CORE_INT2_PIN 2
#define CORE_INT3_PIN 3
#define CORE_INT4_PIN 4
#define CORE_INT5_PIN 5
#define CORE_INT6_PIN 6
#define CORE_INT7_PIN 7
#define CORE_INT8_PIN 8
#define CORE_INT9_PIN 9
#define CORE_INT10_PIN 10
#define CORE_INT11_PIN 11
#define CORE_INT12_PIN 12
#define CORE_INT13_PIN 13
#define CORE_INT14_PIN 14
#define CORE_INT15_PIN 15
#define CORE_INT20_PIN 20
#define CORE_INT21_PIN 21
#define CORE_INT22_PIN 22
#define CORE_INT23_PIN 23


#endif




#ifdef __cplusplus
@@ -509,7 +790,9 @@ static inline void digitalWriteFast(uint8_t pin, uint8_t val)
CORE_PIN25_PORTSET = CORE_PIN25_BITMASK;
} else if (pin == 26) {
CORE_PIN26_PORTSET = CORE_PIN26_BITMASK;
} else if (pin == 27) {
}
#if defined(CORE_PIN27_PORTSET)
else if (pin == 27) {
CORE_PIN27_PORTSET = CORE_PIN27_BITMASK;
} else if (pin == 28) {
CORE_PIN28_PORTSET = CORE_PIN28_BITMASK;
@@ -524,6 +807,7 @@ static inline void digitalWriteFast(uint8_t pin, uint8_t val)
} else if (pin == 33) {
CORE_PIN33_PORTSET = CORE_PIN33_BITMASK;
}
#endif
} else {
if (pin == 0) {
CORE_PIN0_PORTCLEAR = CORE_PIN0_BITMASK;
@@ -579,7 +863,9 @@ static inline void digitalWriteFast(uint8_t pin, uint8_t val)
CORE_PIN25_PORTCLEAR = CORE_PIN25_BITMASK;
} else if (pin == 26) {
CORE_PIN26_PORTCLEAR = CORE_PIN26_BITMASK;
} else if (pin == 27) {
}
#if defined(CORE_PIN27_PORTCLEAR)
else if (pin == 27) {
CORE_PIN27_PORTCLEAR = CORE_PIN27_BITMASK;
} else if (pin == 28) {
CORE_PIN28_PORTCLEAR = CORE_PIN28_BITMASK;
@@ -594,12 +880,13 @@ static inline void digitalWriteFast(uint8_t pin, uint8_t val)
} else if (pin == 33) {
CORE_PIN33_PORTCLEAR = CORE_PIN33_BITMASK;
}
#endif
}
} else {
if (val) {
*portSetRegister(pin) = 1;
*portSetRegister(pin) = digitalPinToBitMask(pin);
} else {
*portClearRegister(pin) = 1;
*portClearRegister(pin) = digitalPinToBitMask(pin);
}
}
}
@@ -663,7 +950,9 @@ static inline uint8_t digitalReadFast(uint8_t pin)
return (CORE_PIN25_PINREG & CORE_PIN25_BITMASK) ? 1 : 0;
} else if (pin == 26) {
return (CORE_PIN26_PINREG & CORE_PIN26_BITMASK) ? 1 : 0;
} else if (pin == 27) {
}
#if defined(CORE_PIN27_PINREG)
else if (pin == 27) {
return (CORE_PIN27_PINREG & CORE_PIN27_BITMASK) ? 1 : 0;
} else if (pin == 28) {
return (CORE_PIN28_PINREG & CORE_PIN28_BITMASK) ? 1 : 0;
@@ -677,11 +966,17 @@ static inline uint8_t digitalReadFast(uint8_t pin)
return (CORE_PIN32_PINREG & CORE_PIN32_BITMASK) ? 1 : 0;
} else if (pin == 33) {
return (CORE_PIN33_PINREG & CORE_PIN33_BITMASK) ? 1 : 0;
} else {
}
#endif
else {
return 0;
}
} else {
#if defined(KINETISK)
return *portInputRegister(pin);
#else
return (*portInputRegister(pin) & digitalPinToBitMask(pin)) ? 1 : 0;
#endif
}
}

@@ -709,12 +1004,21 @@ static inline void analogReadResolution(unsigned int bits) { analogReadRes(bits)
void analogReadAveraging(unsigned int num);
void analog_init(void);


#if defined(__MK20DX128__) || defined(__MK20DX256__)
#define DEFAULT 0
#define INTERNAL 2
#define INTERNAL1V2 2
#define INTERNAL1V1 2
#define EXTERNAL 0

#elif defined(__MKL26Z64__)
#define DEFAULT 0
#define INTERNAL 0
#define EXTERNAL 1
#endif


int touchRead(uint8_t pin);


@@ -805,7 +1109,11 @@ static inline void delayMicroseconds(uint32_t usec)
#if F_CPU < 24000000
"nop" "\n\t"
#endif
#ifdef KINETISL
"sub %0, #1" "\n\t"
#else
"subs %0, #1" "\n\t"
#endif
"bne L_%=_delayMicroseconds" "\n"
: "+r" (n) :
);

+ 224
- 1
teensy3/kinetis.h View File

@@ -84,6 +84,7 @@ enum IRQ_NUMBER_t {
};
#define NVIC_NUM_INTERRUPTS 46
#define DMA_NUM_CHANNELS 4
#define KINETISK
#define KINETISK_UART0
#define KINETISK_UART0_FIFO
#define KINETISK_UART1
@@ -164,46 +165,103 @@ enum IRQ_NUMBER_t {
};
#define NVIC_NUM_INTERRUPTS 95
#define DMA_NUM_CHANNELS 16
#define KINETISK
#define KINETISK_UART0
#define KINETISK_UART0_FIFO
#define KINETISK_UART1
#define KINETISK_UART1_FIFO
#define KINETISK_UART2

#elif defined(__MKL26Z64__)
enum IRQ_NUMBER_t {
IRQ_DMA_CH0 = 0,
IRQ_DMA_CH1 = 1,
IRQ_DMA_CH2 = 2,
IRQ_DMA_CH3 = 3,
IRQ_FTFA = 5,
IRQ_LOW_VOLTAGE = 6,
IRQ_LLWU = 7,
IRQ_I2C0 = 8,
IRQ_I2C1 = 9,
IRQ_SPI0 = 10,
IRQ_SPI1 = 11,
IRQ_UART0_STATUS = 12,
IRQ_UART1_STATUS = 13,
IRQ_UART2_STATUS = 14,
IRQ_ADC0 = 15,
IRQ_CMP0 = 16,
IRQ_FTM0 = 17,
IRQ_FTM1 = 18,
IRQ_FTM2 = 19,
IRQ_RTC_ALARM = 20,
IRQ_RTC_SECOND = 21,
IRQ_PIT = 22,
IRQ_I2S0 = 23,
IRQ_USBOTG = 24,
IRQ_DAC0 = 25,
IRQ_TSI = 26,
IRQ_MCG = 27,
IRQ_LPTMR = 28,
IRQ_SOFTWARE = 29, // TODO: verify this works
IRQ_PORTA = 30,
IRQ_PORTCD = 31
};
#define NVIC_NUM_INTERRUPTS 32
#define DMA_NUM_CHANNELS 4
#define KINETISL
#define KINETISL_UART0
#define KINETISL_UART1
#define KINETISL_UART2

#endif // end of board-specific definitions


#if (F_CPU == 168000000)
#define F_PLL 168000000
#define F_BUS 56000000
#define F_MEM 33600000
#elif (F_CPU == 144000000)
#define F_PLL 144000000
#define F_BUS 48000000
#define F_MEM 28800000
#elif (F_CPU == 120000000)
#define F_PLL 120000000
#define F_BUS 60000000
#define F_MEM 24000000
#elif (F_CPU == 96000000)
#define F_PLL 96000000
#define F_BUS 48000000
#define F_MEM 24000000
#elif (F_CPU == 72000000)
#define F_PLL 72000000
#define F_BUS 36000000
#define F_MEM 24000000
#elif (F_CPU == 48000000)
#define F_PLL 96000000
#if defined(KINETISK)
#define F_BUS 48000000
#elif defined(KINETISL)
#define F_BUS 24000000
#endif
#define F_MEM 24000000
#elif (F_CPU == 24000000)
#define F_PLL 96000000
#define F_BUS 24000000
#define F_MEM 24000000
#elif (F_CPU == 16000000)
#define F_PLL 96000000
#define F_BUS 16000000
#define F_MEM 16000000
#elif (F_CPU == 8000000)
#define F_PLL 96000000
#define F_BUS 8000000
#define F_MEM 8000000
#elif (F_CPU == 4000000)
#define F_PLL 96000000
#define F_BUS 4000000
#define F_MEM 4000000
#elif (F_CPU == 2000000)
#define F_PLL 2000000
#define F_BUS 2000000
#define F_MEM 1000000
#endif
@@ -406,6 +464,8 @@ enum IRQ_NUMBER_t {
#define SIM_SOPT1 (*(volatile uint32_t *)0x40047000) // System Options Register 1
#define SIM_SOPT1CFG (*(volatile uint32_t *)0x40047004) // SOPT1 Configuration Register
#define SIM_SOPT2 (*(volatile uint32_t *)0x40048004) // System Options Register 2
#define SIM_SOPT2_UART0SRC(n) (uint32_t)(((n) & 3) << 26) // UART0 Clock Source, 0=off, 1=FLL/PLL, 2=OSCERCLK, 3=MCGIRCLK
#define SIM_SOPT2_TPMSRC(n) (uint32_t)(((n) & 3) << 24) // TPM Clock Source, 0=off, 1=FLL/PLL, 2=OSCERCLK, 3=MCGIRCLK
#define SIM_SOPT2_USBSRC ((uint32_t)0x00040000) // 0=USB_CLKIN, 1=FFL/PLL
#define SIM_SOPT2_PLLFLLSEL ((uint32_t)0x00010000) // 0=FLL, 1=PLL
#define SIM_SOPT2_TRACECLKSEL ((uint32_t)0x00001000) // 0=MCGOUTCLK, 1=CPU
@@ -432,6 +492,10 @@ enum IRQ_NUMBER_t {
#define SIM_SCGC4_I2C0 ((uint32_t)0x00000040) // I2C0 Clock Gate Control
#define SIM_SCGC4_CMT ((uint32_t)0x00000004) // CMT Clock Gate Control
#define SIM_SCGC4_EWM ((uint32_t)0x00000002) // EWM Clock Gate Control
#ifdef KINETISL
#define SIM_SCGC4_SPI1 ((uint32_t)0x00800000) //
#define SIM_SCGC4_SPI0 ((uint32_t)0x00400000) //
#endif
#define SIM_SCGC5 (*(volatile uint32_t *)0x40048038) // System Clock Gating Control Register 5
#define SIM_SCGC5_PORTE ((uint32_t)0x00002000) // Port E Clock Gate Control
#define SIM_SCGC5_PORTD ((uint32_t)0x00001000) // Port D Clock Gate Control
@@ -445,13 +509,18 @@ enum IRQ_NUMBER_t {
#define SIM_SCGC6_ADC0 ((uint32_t)0x08000000) // ADC0 Clock Gate Control
#define SIM_SCGC6_FTM1 ((uint32_t)0x02000000) // FTM1 Clock Gate Control
#define SIM_SCGC6_FTM0 ((uint32_t)0x01000000) // FTM0 Clock Gate Control
#define SIM_SCGC6_TPM2 ((uint32_t)0x04000000) // FTM1 Clock Gate Control
#define SIM_SCGC6_TPM1 ((uint32_t)0x02000000) // FTM1 Clock Gate Control
#define SIM_SCGC6_TPM0 ((uint32_t)0x01000000) // FTM0 Clock Gate Control
#define SIM_SCGC6_PIT ((uint32_t)0x00800000) // PIT Clock Gate Control
#define SIM_SCGC6_PDB ((uint32_t)0x00400000) // PDB Clock Gate Control
#define SIM_SCGC6_USBDCD ((uint32_t)0x00200000) // USB DCD Clock Gate Control
#define SIM_SCGC6_CRC ((uint32_t)0x00040000) // CRC Clock Gate Control
#define SIM_SCGC6_I2S ((uint32_t)0x00008000) // I2S Clock Gate Control
#ifdef KINETISK
#define SIM_SCGC6_SPI1 ((uint32_t)0x00002000) // SPI1 Clock Gate Control
#define SIM_SCGC6_SPI0 ((uint32_t)0x00001000) // SPI0 Clock Gate Control
#endif
#define SIM_SCGC6_FLEXCAN0 ((uint32_t)0x00000010) // FlexCAN0 Clock Gate Control
#define SIM_SCGC6_DMAMUX ((uint32_t)0x00000002) // DMA Mux Clock Gate Control
#define SIM_SCGC6_FTFL ((uint32_t)0x00000001) // Flash Memory Clock Gate Control
@@ -470,6 +539,8 @@ enum IRQ_NUMBER_t {
#define SIM_UIDMH (*(const uint32_t *)0x40048058) // Unique Identification Register Mid-High
#define SIM_UIDML (*(const uint32_t *)0x4004805C) // Unique Identification Register Mid Low
#define SIM_UIDL (*(const uint32_t *)0x40048060) // Unique Identification Register Low
#define SIM_COPC (*(volatile uint32_t *)0x40048100) // COP Control Register (SIM_COPC)
#define SIM_SRVCOP (*(volatile uint32_t *)0x40048104) // Service COP Register (SIM_SRVCOP)

// Chapter 13: Reset Control Module (RCM)
#define RCM_SRS0 (*(volatile uint8_t *)0x4007F000) // System Reset Status Register 0
@@ -532,6 +603,7 @@ enum IRQ_NUMBER_t {
#define LLWU_RST (*(volatile uint8_t *)0x4007C00A) // LLWU Reset Enable register

// Chapter 17: Miscellaneous Control Module (MCM)
#if defined(KINETISK)
#define MCM_PLASC (*(volatile uint16_t *)0xE0080008) // Crossbar Switch (AXBS) Slave Configuration
#define MCM_PLAMC (*(volatile uint16_t *)0xE008000A) // Crossbar Switch (AXBS) Master Configuration
#define MCM_PLACR (*(volatile uint32_t *)0xE008000C) // Crossbar Switch (AXBS) Control Register (MK20DX128)
@@ -541,6 +613,12 @@ enum IRQ_NUMBER_t {
#define MCM_CR_SRAMLAP(n) ((uint32_t)(((n) & 0x03) << 28)) // SRAM_L priority, 0=RR, 1=favor DMA, 2=CPU, 3=DMA
#define MCM_CR_SRAMUWP ((uint32_t)0x04000000) // SRAM_U write protect
#define MCM_CR_SRAMUAP(n) ((uint32_t)(((n) & 0x03) << 24)) // SRAM_U priority, 0=RR, 1=favor DMA, 2=CPU, 3=DMA
#elif defined(KINETISL)
#define MCM_PLASC (*(volatile uint16_t *)0xF0003008) // Crossbar Switch (AXBS) Slave Configuration
#define MCM_PLAMC (*(volatile uint16_t *)0xF000300A) // Crossbar Switch (AXBS) Master Configuration
#define MCM_PLACR (*(volatile uint32_t *)0xF000300C) // Platform Control Register
#define MCM_CPO (*(volatile uint32_t *)0xF0003040) // Compute Operation Control Register
#endif

// Crossbar Switch (AXBS) - only programmable on MK20DX256
#define AXBS_PRS0 (*(volatile uint32_t *)0x40004000) // Priority Registers Slave 0
@@ -1689,6 +1767,8 @@ enum IRQ_NUMBER_t {
#define FTM1_INVCTRL (*(volatile uint32_t *)0x40039090) // FTM Inverting Control
#define FTM1_SWOCTRL (*(volatile uint32_t *)0x40039094) // FTM Software Output Control
#define FTM1_PWMLOAD (*(volatile uint32_t *)0x40039098) // FTM PWM Load

#if defined(KINETISK)
#define FTM2_SC (*(volatile uint32_t *)0x400B8000) // Status And Control
#define FTM2_CNT (*(volatile uint32_t *)0x400B8004) // Counter
#define FTM2_MOD (*(volatile uint32_t *)0x400B8008) // Modulo
@@ -1716,6 +1796,17 @@ enum IRQ_NUMBER_t {
#define FTM2_INVCTRL (*(volatile uint32_t *)0x400B8090) // FTM Inverting Control
#define FTM2_SWOCTRL (*(volatile uint32_t *)0x400B8094) // FTM Software Output Control
#define FTM2_PWMLOAD (*(volatile uint32_t *)0x400B8098) // FTM PWM Load
#elif defined(KINETISL)
#define FTM2_SC (*(volatile uint32_t *)0x4003A000) // Status And Control
#define FTM2_CNT (*(volatile uint32_t *)0x4003A004) // Counter
#define FTM2_MOD (*(volatile uint32_t *)0x4003A008) // Modulo
#define FTM2_C0SC (*(volatile uint32_t *)0x4003A00C) // Channel 0 Status And Control
#define FTM2_C0V (*(volatile uint32_t *)0x4003A010) // Channel 0 Value
#define FTM2_C1SC (*(volatile uint32_t *)0x4003A014) // Channel 1 Status And Control
#define FTM2_C1V (*(volatile uint32_t *)0x4003A018) // Channel 1 Value
#define FTM2_STATUS (*(volatile uint32_t *)0x4003A050) // Capture And Compare Status
#define FTM2_CONF (*(volatile uint32_t *)0x4003A084) // Configuration
#endif

// Chapter 36: Periodic Interrupt Timer (PIT)
#define PIT_MCR (*(volatile uint32_t *)0x40037000) // PIT Module Control Register
@@ -1929,6 +2020,7 @@ enum IRQ_NUMBER_t {
#define USBDCD_TIMER1 (*(volatile uint32_t *)0x40035014) // TIMER1 register
#define USBDCD_TIMER2 (*(volatile uint32_t *)0x40035018) // TIMER2 register

#if defined(KINETISK)
// Chapter 43: SPI (DSPI)
typedef struct __attribute__((packed)) {
volatile uint32_t MCR; // 0
@@ -2017,6 +2109,70 @@ typedef struct __attribute__((packed)) {
#define SPI0_RXFR2 (*(volatile uint32_t *)0x4002C084) // DSPI Receive FIFO Registers
#define SPI0_RXFR3 (*(volatile uint32_t *)0x4002C088) // DSPI Receive FIFO Registers

#elif defined(KINETISL)
#define SPI0_S (*(volatile uint8_t *)0x40076000) // Status
#define SPI_S_SPRF ((uint8_t)0x80) // Read Buffer Full Flag
#define SPI_S_SPMF ((uint8_t)0x40) // Match Flag
#define SPI_S_SPTEF ((uint8_t)0x20) // Transmit Buffer Empty Flag
#define SPI_S_MODF ((uint8_t)0x10) // Fault Flag
#define SPI_S_RNFULLF ((uint8_t)0x08) // Receive FIFO nearly full flag
#define SPI_S_TNEAREF ((uint8_t)0x04) // Transmit FIFO nearly empty flag
#define SPI_S_TXFULLF ((uint8_t)0x02) // Transmit FIFO full flag
#define SPI_S_RFIFOEF ((uint8_t)0x01) // Read FIFO empty flag
#define SPI0_BR (*(volatile uint8_t *)0x40076001) // Baud Rate
#define SPI_BR_SPPR(n) (((n) & 7) << 4) // Prescale = N+1
#define SPI_BR_SPR(n) (((n) & 15) << 0) // Baud Rate Divisor = 2^(N+1) : 0-8 -> 2 to 512
#define SPI0_C2 (*(volatile uint8_t *)0x40076002) // Control Register 2
#define SPI_C2_SPMIE ((uint8_t)0x80) // Match Interrupt Enable
#define SPI_C2_SPIMODE ((uint8_t)0x40) // 0 = 8 bit mode, 1 = 16 bit mode
#define SPI_C2_TXDMAE ((uint8_t)0x20) // Transmit DMA enable
#define SPI_C2_MODFEN ((uint8_t)0x10) // Master Mode-Fault Function Enable
#define SPI_C2_BIDIROE ((uint8_t)0x08) // Bidirectional Mode Output Enable
#define SPI_C2_RXDMAE ((uint8_t)0x04) // Receive DMA enable
#define SPI_C2_SPISWAI ((uint8_t)0x02) // SPI Stop in Wait Mode
#define SPI_C2_SPC0 ((uint8_t)0x01) // SPI Pin Control, 0=normal, 1=single bidirectional
#define SPI0_C1 (*(volatile uint8_t *)0x40076003) // Control Register 1
#define SPI_C1_SPIE ((uint8_t)0x80) // Interrupt Enable
#define SPI_C1_SPE ((uint8_t)0x40) // SPI System Enable
#define SPI_C1_SPTIE ((uint8_t)0x20) // Transmit Interrupt Enable
#define SPI_C1_MSTR ((uint8_t)0x10) // Master/Slave Mode: 0=slave, 1=master
#define SPI_C1_CPOL ((uint8_t)0x08) // Clock Polarity
#define SPI_C1_CPHA ((uint8_t)0x04) // Clock Phase
#define SPI_C1_SSOE ((uint8_t)0x02) // Slave Select Output Enable
#define SPI_C1_LSBFE ((uint8_t)0x01) // LSB First: 0=MSB First, 1=LSB First
#define SPI0_ML (*(volatile uint8_t *)0x40076004) // Match Low
#define SPI0_MH (*(volatile uint8_t *)0x40076005) // Match High
#define SPI0_DL (*(volatile uint8_t *)0x40076006) // Data Low
#define SPI0_DH (*(volatile uint8_t *)0x40076007) // Data High
#define SPI0_CI (*(volatile uint8_t *)0x4007600A) // clear interrupt
#define SPI_CI_TXFERR ((uint8_t)0x80) // Transmit FIFO error flag
#define SPI_CI_RXFERR ((uint8_t)0x40) // Receive FIFO error flag
#define SPI_CI_TXFOF ((uint8_t)0x20) // Transmit FIFO overflow flag
#define SPI_CI_RXFOF ((uint8_t)0x10) // Receive FIFO overflow flag
#define SPI_CI_TNEAREFCI ((uint8_t)0x08) // Transmit FIFO nearly empty flag clear interrupt
#define SPI_CI_RNFULLFCI ((uint8_t)0x04) // Receive FIFO nearly full flag clear interrupt
#define SPI_CI_SPTEFCI ((uint8_t)0x02) // Transmit FIFO empty flag clear interrupt
#define SPI_CI_SPRFCI ((uint8_t)0x01) // Receive FIFO full flag clear interrupt
#define SPI0_C3 (*(volatile uint8_t *)0x4007600B) // Control Register 3
#define SPI_C3_TNEAREF_MARK ((uint8_t)0x20) // Transmit FIFO nearly empty watermark
#define SPI_C3_RNFULLF_MARK ((uint8_t)0x10) // Receive FIFO nearly full watermark
#define SPI_C3_INTCLR ((uint8_t)0x08) // Interrupt clearing mechanism select
#define SPI_C3_TNEARIEN ((uint8_t)0x04) // Transmit FIFO nearly empty interrupt enable
#define SPI_C3_RNFULLIEN ((uint8_t)0x02) // Receive FIFO nearly full interrupt enable
#define SPI_C3_FIFOMODE ((uint8_t)0x01) // FIFO mode enable
#define SPI1_S (*(volatile uint8_t *)0x40077000) // Status
#define SPI1_BR (*(volatile uint8_t *)0x40077001) // Baud Rate
#define SPI1_C2 (*(volatile uint8_t *)0x40077002) // Control Register 2
#define SPI1_C1 (*(volatile uint8_t *)0x40077003) // Control Register 1
#define SPI1_ML (*(volatile uint8_t *)0x40077004) // Match Low
#define SPI1_MH (*(volatile uint8_t *)0x40077005) // Match High
#define SPI1_DL (*(volatile uint8_t *)0x40077006) // Data Low
#define SPI1_DH (*(volatile uint8_t *)0x40077007) // Data High
#define SPI1_CI (*(volatile uint8_t *)0x4007700A) // clear interrupt
#define SPI1_C3 (*(volatile uint8_t *)0x4007700B) // Control Register 3
#endif


// Chapter 44: Inter-Integrated Circuit (I2C)
#define I2C0_A1 (*(volatile uint8_t *)0x40066000) // I2C Address Register 1
#define I2C0_F (*(volatile uint8_t *)0x40066001) // I2C Frequency Divider register
@@ -2494,7 +2650,41 @@ typedef struct __attribute__((packed)) {
#define GPIOE_PDIR (*(volatile uint32_t *)0x400FF110) // Port Data Input Register
#define GPIOE_PDDR (*(volatile uint32_t *)0x400FF114) // Port Data Direction Register

#if defined(KINETISL)
#define FGPIOA_PDOR (*(volatile uint32_t *)0xF8000000) // Port Data Output Register
#define FGPIOA_PSOR (*(volatile uint32_t *)0xF8000004) // Port Set Output Register
#define FGPIOA_PCOR (*(volatile uint32_t *)0xF8000008) // Port Clear Output Register
#define FGPIOA_PTOR (*(volatile uint32_t *)0xF800000C) // Port Toggle Output Register
#define FGPIOA_PDIR (*(volatile uint32_t *)0xF8000010) // Port Data Input Register
#define FGPIOA_PDDR (*(volatile uint32_t *)0xF8000014) // Port Data Direction Register
#define FGPIOB_PDOR (*(volatile uint32_t *)0xF8000040) // Port Data Output Register
#define FGPIOB_PSOR (*(volatile uint32_t *)0xF8000044) // Port Set Output Register
#define FGPIOB_PCOR (*(volatile uint32_t *)0xF8000048) // Port Clear Output Register
#define FGPIOB_PTOR (*(volatile uint32_t *)0xF800004C) // Port Toggle Output Register
#define FGPIOB_PDIR (*(volatile uint32_t *)0xF8000050) // Port Data Input Register
#define FGPIOB_PDDR (*(volatile uint32_t *)0xF8000054) // Port Data Direction Register
#define FGPIOC_PDOR (*(volatile uint32_t *)0xF8000080) // Port Data Output Register
#define FGPIOC_PSOR (*(volatile uint32_t *)0xF8000084) // Port Set Output Register
#define FGPIOC_PCOR (*(volatile uint32_t *)0xF8000088) // Port Clear Output Register
#define FGPIOC_PTOR (*(volatile uint32_t *)0xF800008C) // Port Toggle Output Register
#define FGPIOC_PDIR (*(volatile uint32_t *)0xF8000090) // Port Data Input Register
#define FGPIOC_PDDR (*(volatile uint32_t *)0xF8000094) // Port Data Direction Register
#define FGPIOD_PDOR (*(volatile uint32_t *)0xF80000C0) // Port Data Output Register
#define FGPIOD_PSOR (*(volatile uint32_t *)0xF80000C4) // Port Set Output Register
#define FGPIOD_PCOR (*(volatile uint32_t *)0xF80000C8) // Port Clear Output Register
#define FGPIOD_PTOR (*(volatile uint32_t *)0xF80000CC) // Port Toggle Output Register
#define FGPIOD_PDIR (*(volatile uint32_t *)0xF80000D0) // Port Data Input Register
#define FGPIOD_PDDR (*(volatile uint32_t *)0xF80000D4) // Port Data Direction Register
#define FGPIOE_PDOR (*(volatile uint32_t *)0xF8000100) // Port Data Output Register
#define FGPIOE_PSOR (*(volatile uint32_t *)0xF8000104) // Port Set Output Register
#define FGPIOE_PCOR (*(volatile uint32_t *)0xF8000108) // Port Clear Output Register
#define FGPIOE_PTOR (*(volatile uint32_t *)0xF800010C) // Port Toggle Output Register
#define FGPIOE_PDIR (*(volatile uint32_t *)0xF8000110) // Port Data Input Register
#define FGPIOE_PDDR (*(volatile uint32_t *)0xF8000114) // Port Data Direction Register
#endif

// Chapter 48: Touch sense input (TSI)
#if defined(KINETISK)
#define TSI0_GENCS (*(volatile uint32_t *)0x40045000) // General Control and Status Register
#define TSI_GENCS_LPCLKS ((uint32_t)0x10000000) //
#define TSI_GENCS_LPSCNITV(n) (((n) & 15) << 24) //
@@ -2529,6 +2719,32 @@ typedef struct __attribute__((packed)) {
#define TSI0_CNTR13 (*(volatile uint32_t *)0x40045118) // Counter Register
#define TSI0_CNTR15 (*(volatile uint32_t *)0x4004511C) // Counter Register
#define TSI0_THRESHOLD (*(volatile uint32_t *)0x40045120) // Low Power Channel Threshold Register
#elif defined(KINETISL)
#define TSI0_GENCS (*(volatile uint32_t *)0x40045000) // General Control and Status
#define TSI_GENCS_OUTRGF ((uint32_t)0x80000000) // Out of Range Flag
#define TSI_GENCS_ESOR ((uint32_t)0x10000000) // End-of-scan or Out-of-Range Interrupt Selection
#define TSI_GENCS_MODE(n) (((n) & 15) << 24) // analog modes & status
#define TSI_GENCS_REFCHRG(n) (((n) & 7) << 21) // reference charge and discharge current
#define TSI_GENCS_DVOLT(n) (((n) & 3) << 19) // voltage rails
#define TSI_GENCS_EXTCHRG(n) (((n) & 7) << 16) // electrode charge and discharge current
#define TSI_GENCS_PS(n) (((n) & 7) << 13) // prescaler
#define TSI_GENCS_NSCN(n) (((n) & 31) << 8) // scan number
#define TSI_GENCS_TSIEN ((uint32_t)0x00000080) // Enable
#define TSI_GENCS_TSIIEN ((uint32_t)0x00000040) // Interrupt Enable
#define TSI_GENCS_STPE ((uint32_t)0x00000020) // STOP Enable
#define TSI_GENCS_STM ((uint32_t)0x00000010) // Trigger Mode
#define TSI_GENCS_SCNIP ((uint32_t)0x00000008) // Scan In Progress Status
#define TSI_GENCS_EOSF ((uint32_t)0x00000004) // End of Scan Flag
#define TSI_GENCS_CURSW ((uint32_t)0x00000002) // current sources swapped
#define TSI0_DATA (*(volatile uint32_t *)0x40045004) // Data
#define TSI_DATA_TSICH(n) (((n) & 15) << 28) // channel
#define TSI_DATA_DMAEN ((uint32_t)0x00800000) // DMA Transfer Enabled
#define TSI_DATA_SWTS ((uint32_t)0x00400000) // Software Trigger Start
#define TSI_DATA_TSICNT(n) (((n) & 65535) << 0) // Conversion Counter Value
#define TSI0_TSHD (*(volatile uint32_t *)0x40045008) // Threshold
#define TSI_TSHD_THRESH(n) (((n) & 65535) << 16) // High wakeup threshold
#define TSI_TSHD_THRESL(n) (((n) & 65535) << 0) // Low wakeup threshold
#endif

// Nested Vectored Interrupt Controller, Table 3-4 & ARMv7 ref, appendix B3.4 (page 750)
#define NVIC_ENABLE_IRQ(n) (*((volatile uint32_t *)0xE000E100 + ((n) >> 5)) = (1 << ((n) & 31)))
@@ -2548,9 +2764,13 @@ typedef struct __attribute__((packed)) {
// 0 = highest priority
// Cortex-M4: 0,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240
// Cortex-M0: 0,64,128,192
#ifdef KINETISK
#define NVIC_SET_PRIORITY(irqnum, priority) (*((volatile uint8_t *)0xE000E400 + (irqnum)) = (uint8_t)(priority))
#define NVIC_GET_PRIORITY(irqnum) (*((uint8_t *)0xE000E400 + (irqnum)))

#else
#define NVIC_SET_PRIORITY(irqnum, priority) (*((uint32_t *)0xE000E400 + ((irqnum) >> 2)) = (*((uint32_t *)0xE000E400 + ((irqnum) >> 2)) & (~(0xFF << (8 * ((irqnum) & 3))))) | (((priority) & 0xFF) << (8 * ((irqnum) & 3))))
#define NVIC_GET_PRIORITY(irqnum) (*((uint32_t *)0xE000E400 + ((irqnum) >> 2)) >> (8 * ((irqnum) & 3)) & 255)
#endif



@@ -2644,6 +2864,7 @@ extern void can0_rx_warn_isr(void);
extern void can0_wakeup_isr(void);
extern void i2s0_tx_isr(void);
extern void i2s0_rx_isr(void);
extern void i2s0_isr(void);
extern void uart0_lon_isr(void);
extern void uart0_status_isr(void);
extern void uart0_error_isr(void);
@@ -2673,6 +2894,7 @@ extern void pit0_isr(void);
extern void pit1_isr(void);
extern void pit2_isr(void);
extern void pit3_isr(void);
extern void pit_isr(void);
extern void pdb_isr(void);
extern void usb_isr(void);
extern void usb_charge_isr(void);
@@ -2686,6 +2908,7 @@ extern void portb_isr(void);
extern void portc_isr(void);
extern void portd_isr(void);
extern void porte_isr(void);
extern void portcd_isr(void);
extern void software_isr(void);

extern void (* _VectorsRam[NVIC_NUM_INTERRUPTS+16])(void);

+ 136
- 14
teensy3/mk20dx128.c View File

@@ -29,7 +29,8 @@
*/

#include "kinetis.h"

//#include "core_pins.h" // testing only
//#include "ser_print.h" // testing only

extern unsigned long _stext;
extern unsigned long _etext;
@@ -51,6 +52,51 @@ void __libc_init_array(void);

void fault_isr(void)
{
#if 0
uint32_t addr;
digitalWriteFast(15, HIGH);
ser_print("\nfault: \n??: ");
asm("ldr %0, [sp, #52]" : "=r" (addr) ::);
ser_print_hex32(addr);
ser_print("\n??: ");
asm("ldr %0, [sp, #48]" : "=r" (addr) ::);
ser_print_hex32(addr);
ser_print("\n??: ");
asm("ldr %0, [sp, #44]" : "=r" (addr) ::);
ser_print_hex32(addr);
ser_print("\npsr:");
asm("ldr %0, [sp, #40]" : "=r" (addr) ::);
ser_print_hex32(addr);
ser_print("\nadr:");
asm("ldr %0, [sp, #36]" : "=r" (addr) ::);
ser_print_hex32(addr);
ser_print("\nlr: ");
asm("ldr %0, [sp, #32]" : "=r" (addr) ::);
ser_print_hex32(addr);
ser_print("\nr12:");
asm("ldr %0, [sp, #28]" : "=r" (addr) ::);
ser_print_hex32(addr);
ser_print("\nr3: ");
asm("ldr %0, [sp, #24]" : "=r" (addr) ::);
ser_print_hex32(addr);
ser_print("\nr2: ");
asm("ldr %0, [sp, #20]" : "=r" (addr) ::);
ser_print_hex32(addr);
ser_print("\nr1: ");
asm("ldr %0, [sp, #16]" : "=r" (addr) ::);
ser_print_hex32(addr);
ser_print("\nr0: ");
asm("ldr %0, [sp, #12]" : "=r" (addr) ::);
ser_print_hex32(addr);
ser_print("\nr4: ");
asm("ldr %0, [sp, #8]" : "=r" (addr) ::);
ser_print_hex32(addr);
ser_print("\nlr: ");
asm("ldr %0, [sp, #4]" : "=r" (addr) ::);
ser_print_hex32(addr);
ser_print("\n");
asm("ldr %0, [sp, #0]" : "=r" (addr) ::);
#endif
while (1) {
// keep polling some communication while in fault
// mode, so we don't completely die.
@@ -73,10 +119,10 @@ void systick_default_isr(void)
}

void nmi_isr(void) __attribute__ ((weak, alias("unused_isr")));
void hard_fault_isr(void) __attribute__ ((weak, alias("unused_isr")));
void memmanage_fault_isr(void) __attribute__ ((weak, alias("unused_isr")));
void bus_fault_isr(void) __attribute__ ((weak, alias("unused_isr")));
void usage_fault_isr(void) __attribute__ ((weak, alias("unused_isr")));
void hard_fault_isr(void) __attribute__ ((weak, alias("fault_isr")));
void memmanage_fault_isr(void) __attribute__ ((weak, alias("fault_isr")));
void bus_fault_isr(void) __attribute__ ((weak, alias("fault_isr")));
void usage_fault_isr(void) __attribute__ ((weak, alias("fault_isr")));
void svcall_isr(void) __attribute__ ((weak, alias("unused_isr")));
void debugmonitor_isr(void) __attribute__ ((weak, alias("unused_isr")));
void pendablesrvreq_isr(void) __attribute__ ((weak, alias("unused_isr")));
@@ -120,6 +166,7 @@ void can0_rx_warn_isr(void) __attribute__ ((weak, alias("unused_isr")));
void can0_wakeup_isr(void) __attribute__ ((weak, alias("unused_isr")));
void i2s0_tx_isr(void) __attribute__ ((weak, alias("unused_isr")));
void i2s0_rx_isr(void) __attribute__ ((weak, alias("unused_isr")));
void i2s0_isr(void) __attribute__ ((weak, alias("unused_isr")));
void uart0_lon_isr(void) __attribute__ ((weak, alias("unused_isr")));
void uart0_status_isr(void) __attribute__ ((weak, alias("unused_isr")));
void uart0_error_isr(void) __attribute__ ((weak, alias("unused_isr")));
@@ -145,6 +192,7 @@ void ftm3_isr(void) __attribute__ ((weak, alias("unused_isr")));
void cmt_isr(void) __attribute__ ((weak, alias("unused_isr")));
void rtc_alarm_isr(void) __attribute__ ((weak, alias("unused_isr")));
void rtc_seconds_isr(void) __attribute__ ((weak, alias("unused_isr")));
void pit_isr(void) __attribute__ ((weak, alias("unused_isr")));
void pit0_isr(void) __attribute__ ((weak, alias("unused_isr")));
void pit1_isr(void) __attribute__ ((weak, alias("unused_isr")));
void pit2_isr(void) __attribute__ ((weak, alias("unused_isr")));
@@ -162,12 +210,15 @@ void portb_isr(void) __attribute__ ((weak, alias("unused_isr")));
void portc_isr(void) __attribute__ ((weak, alias("unused_isr")));
void portd_isr(void) __attribute__ ((weak, alias("unused_isr")));
void porte_isr(void) __attribute__ ((weak, alias("unused_isr")));
void portcd_isr(void) __attribute__ ((weak, alias("unused_isr")));
void software_isr(void) __attribute__ ((weak, alias("unused_isr")));

#if defined(__MK20DX128__)
__attribute__ ((section(".dmabuffers"), used, aligned(256)))
#else
#elif defined(__MK20DX256__)
__attribute__ ((section(".dmabuffers"), used, aligned(512)))
#elif defined(__MKL26Z64__)
__attribute__ ((section(".dmabuffers"), used, aligned(256)))
#endif
void (* _VectorsRam[NVIC_NUM_INTERRUPTS+16])(void);

@@ -333,12 +384,42 @@ void (* const _VectorsFlash[NVIC_NUM_INTERRUPTS+16])(void) =
unused_isr, // 108 --
unused_isr, // 109 --
software_isr, // 110 Software interrupt
#elif defined(__MKL26Z64__)
dma_ch0_isr, // 16 DMA channel 0 transfer complete
dma_ch1_isr, // 17 DMA channel 1 transfer complete
dma_ch2_isr, // 18 DMA channel 2 transfer complete
dma_ch3_isr, // 19 DMA channel 3 transfer complete
unused_isr, // 20 --
flash_cmd_isr, // 21 Flash Memory Command complete
low_voltage_isr, // 22 Low-voltage detect/warning
wakeup_isr, // 23 Low Leakage Wakeup
i2c0_isr, // 24 I2C0
i2c1_isr, // 25 I2C1
spi0_isr, // 26 SPI0
spi1_isr, // 27 SPI1
uart0_status_isr, // 28 UART0 status & error
uart1_status_isr, // 29 UART1 status & error
uart2_status_isr, // 30 UART2 status & error
adc0_isr, // 31 ADC0
cmp0_isr, // 32 CMP0
ftm0_isr, // 33 FTM0
ftm1_isr, // 34 FTM1
ftm2_isr, // 35 FTM2
rtc_alarm_isr, // 36 RTC Alarm interrupt
rtc_seconds_isr, // 37 RTC Seconds interrupt
pit_isr, // 38 PIT Both Channels
i2s0_isr, // 39 I2S0 Transmit & Receive
usb_isr, // 40 USB OTG
dac0_isr, // 41 DAC0
tsi0_isr, // 42 TSI0
mcg_isr, // 43 MCG
lptmr_isr, // 44 Low Power Timer
software_isr, // 45 Software interrupt
porta_isr, // 46 Pin detect (Port A)
portcd_isr, // 47 Pin detect (Port C and D)
#endif
};

//void usb_isr(void)
//{
//}

__attribute__ ((section(".flashconfig"), used))
const uint8_t flashconfigbytes[16] = {
@@ -356,11 +437,18 @@ const uint8_t flashconfigbytes[16] = {
extern void rtc_set(unsigned long t);


static void startup_default_early_hook(void) { WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE; }
static void startup_default_early_hook(void) {
#if defined(KINETISK)
WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE;
#elif defined(KINETISL)
SIM_COPC = 0; // disable the watchdog
#endif
}
static void startup_default_late_hook(void) {}
void startup_early_hook(void) __attribute__ ((weak, alias("startup_default_early_hook")));
void startup_late_hook(void) __attribute__ ((weak, alias("startup_default_late_hook")));


__attribute__ ((section(".startup")))
void ResetHandler(void)
{
@@ -370,11 +458,14 @@ void ResetHandler(void)
#if F_CPU <= 2000000
volatile int n;
#endif
//volatile int count;

#ifdef KINETISK
WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
__asm__ volatile ("nop");
__asm__ volatile ("nop");
#endif
// programs using the watchdog timer or needing to initialize hardware as
// early as possible can implement startup_early_hook()
startup_early_hook();
@@ -387,13 +478,29 @@ void ResetHandler(void)
SIM_SCGC3 = SIM_SCGC3_ADC1 | SIM_SCGC3_FTM2;
SIM_SCGC5 = 0x00043F82; // clocks active to all GPIO
SIM_SCGC6 = SIM_SCGC6_RTC | SIM_SCGC6_FTM0 | SIM_SCGC6_FTM1 | SIM_SCGC6_ADC0 | SIM_SCGC6_FTFL;
#elif defined(__MKL26Z64__)
SIM_SCGC4 = SIM_SCGC4_USBOTG | 0xF0000030;
SIM_SCGC5 = 0x00003F82; // clocks active to all GPIO
SIM_SCGC6 = SIM_SCGC6_ADC0 | SIM_SCGC6_TPM0 | SIM_SCGC6_TPM1 | SIM_SCGC6_TPM2 | SIM_SCGC6_FTFL;
#endif
#if 0
// testing only, enable ser_print
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV4(1);
MCG_C4 |= MCG_C4_DMX32 | MCG_C4_DRST_DRS(1);
SIM_SOPT2 = SIM_SOPT2_UART0SRC(1) | SIM_SOPT2_TPMSRC(1);
SIM_SCGC4 |= 0x00000400;
UART0_BDH = 0;
UART0_BDL = 26; // 115200 at 48 MHz
UART0_C2 = UART_C2_TE;
PORTB_PCR17 = PORT_PCR_MUX(3);
#endif
#ifdef KINETISK
// if the RTC oscillator isn't enabled, get it started early
if (!(RTC_CR & RTC_CR_OSCE)) {
RTC_SR = 0;
RTC_CR = RTC_CR_SC16P | RTC_CR_SC4P | RTC_CR_OSCE;
}

#endif
// release I/O pins hold, if we woke up from VLLS mode
if (PMC_REGSC & PMC_REGSC_ACKISO) PMC_REGSC |= PMC_REGSC_ACKISO;

@@ -449,6 +556,7 @@ void ResetHandler(void)
while ((MCG_S & MCG_S_IREFST) != 0) ;
// wait for MCGOUT to use oscillator
while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2)) ;

// now in FBE mode
// C1[CLKS] bits are written to 10
// C1[IREFS] bit is written to 0
@@ -487,7 +595,6 @@ void ResetHandler(void)
// now we're in PBE mode
#endif
#endif

// now program the clock dividers
#if F_CPU == 168000000
// config divisors: 168 MHz core, 56 MHz bus, 33.6 MHz flash, USB = 168 * 2 / 7
@@ -511,12 +618,20 @@ void ResetHandler(void)
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(2) | SIM_CLKDIV2_USBFRAC;
#elif F_CPU == 48000000
// config divisors: 48 MHz core, 48 MHz bus, 24 MHz flash, USB = 96 / 2
#if defined(KINETISK)
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(3);
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1);
#elif defined(KINETISL)
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV4(1);
#endif
#elif F_CPU == 24000000
// config divisors: 24 MHz core, 24 MHz bus, 24 MHz flash, USB = 96 / 2
#if defined(KINETISK)
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV4(3);
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1);
#elif defined(KINETISL)
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV4(0);
#endif
#elif F_CPU == 16000000
// config divisors: 16 MHz core, 16 MHz bus, 16 MHz flash
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV4(0);
@@ -547,7 +662,13 @@ void ResetHandler(void)
while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)) ;
// now we're in PEE mode
// USB uses PLL clock, trace is CPU clock, CLKOUT=OSCERCLK0
SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_PLLFLLSEL | SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL(6);
#if defined(KINETISK)
SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_PLLFLLSEL | SIM_SOPT2_TRACECLKSEL
| SIM_SOPT2_CLKOUTSEL(6);
#elif defined(KINETISL)
SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_PLLFLLSEL | SIM_SOPT2_CLKOUTSEL(6)
| SIM_SOPT2_UART0SRC(1) | SIM_SOPT2_TPMSRC(1);
#endif
#else
SIM_SOPT2 = SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL(3);
#endif
@@ -565,12 +686,13 @@ void ResetHandler(void)
__enable_irq();

_init_Teensyduino_internal_();
#if defined(KINETISK)
if (RTC_SR & RTC_SR_TIF) {
// TODO: this should probably set the time more agressively, if
// we could reliably detect the first reboot after programming.
rtc_set(TIME_T);
}
#endif
__libc_init_array();

startup_late_hook();

+ 110
- 0
teensy3/mkl26z64.ld View File

@@ -0,0 +1,110 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2014 PJRC.COM, LLC.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* 1. The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 2. If the Software is incorporated into a build system that allows
* selection among a list of target devices, then similar target
* devices manufactured by PJRC.COM must be included in the list of
* target devices and selectable in the same manner.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 60K
RAM (rwx) : ORIGIN = 0x1FFFF800, LENGTH = 8K
}


SECTIONS
{
.text : {
. = 0;
KEEP(*(.vectors))
*(.startup*)
/* TODO: does linker detect startup overflow onto flashconfig? */
. = 0x400;
KEEP(*(.flashconfig*))
*(.text*)
*(.rodata*)
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} > FLASH = 0xFF

.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
__exidx_end = .;
} > FLASH
_etext = .;

.usbdescriptortable (NOLOAD) : {
/* . = ORIGIN(RAM); */
. = ALIGN(512);
*(.usbdescriptortable*)
} > RAM

.dmabuffers (NOLOAD) : {
. = ALIGN(4);
*(.dmabuffers*)
} > RAM

.usbbuffers (NOLOAD) : {
. = ALIGN(4);
*(.usbbuffers*)
} > RAM

.data : AT (_etext) {
. = ALIGN(4);
_sdata = .;
*(.fastrun*)
*(.data*)
. = ALIGN(4);
_edata = .;
} > RAM

.noinit (NOLOAD) : {
*(.noinit*)
} > RAM

.bss : {
. = ALIGN(4);
_sbss = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
__bss_end = .;
} > RAM

_estack = ORIGIN(RAM) + LENGTH(RAM);
}



+ 53
- 9
teensy3/pins_arduino.h View File

@@ -33,6 +33,7 @@

#include <stdint.h>

// A0-A9 are always digital 14-23, for Arduino compatibility
const static uint8_t A0 = 14;
const static uint8_t A1 = 15;
const static uint8_t A2 = 16;
@@ -43,18 +44,28 @@ const static uint8_t A6 = 20;
const static uint8_t A7 = 21;
const static uint8_t A8 = 22;
const static uint8_t A9 = 23;
#if defined(__MK20DX128__)
const static uint8_t A10 = 34;
const static uint8_t A11 = 35;
const static uint8_t A12 = 36;
const static uint8_t A13 = 37;
#elif defined(__MK20DX256__)
const static uint8_t A10 = 34;
const static uint8_t A11 = 35;
const static uint8_t A12 = 36;
const static uint8_t A13 = 37;
const static uint8_t A14 = 40;

const static uint8_t A15 = 26;
const static uint8_t A16 = 27;
const static uint8_t A17 = 28;
const static uint8_t A18 = 29;
const static uint8_t A19 = 30;
const static uint8_t A20 = 31;
#elif defined(__MKL26Z64__)
const static uint8_t A10 = 24;
const static uint8_t A11 = 25;
const static uint8_t A12 = 26;
#endif

const static uint8_t SS = 10;
const static uint8_t MOSI = 11;
@@ -65,22 +76,34 @@ const static uint8_t SDA = 18;
const static uint8_t SCL = 19;


#define NUM_DIGITAL_PINS 34
#define NUM_ANALOG_INPUTS 14
#define NUM_DIGITAL_PINS CORE_NUM_DIGITAL
#define NUM_ANALOG_INPUTS CORE_NUM_ANALOG

#define analogInputToDigitalPin(p) (((p) < 10) ? (p) + 14 : -1)
#define digitalPinHasPWM(p) (((p) >= 3 && (p) <= 6) || (p) == 9 || (p) == 10 || ((p) >= 20 && (p) <= 23))

#define NOT_AN_INTERRUPT -1
#define digitalPinToInterrupt(p) ((p) < NUM_DIGITAL_PINS ? (p) : -1)


#if defined(__MK20DX128__)
#define analogInputToDigitalPin(p) (((p) <= 9) ? (p) + 14 : (((p) <= 13) ? (p) + 24 : -1))
#define digitalPinHasPWM(p) (((p) >= 3 && (p) <= 6) || (p) == 9 || (p) == 10 || ((p) >= 20 && (p) <= 23))
#define digitalPinToInterrupt(p) ((p) < NUM_DIGITAL_PINS ? (p) : -1)
#elif defined(__MK20DX256__)
#define analogInputToDigitalPin(p) (((p) <= 9) ? (p) + 14 : (((p) <= 13) ? (p) + 24 : (((p) == 14) ? 40 : (((p) <= 20) ? (p) + 11 : -1))))
#define digitalPinHasPWM(p) (((p) >= 3 && (p) <= 6) || (p) == 9 || (p) == 10 || ((p) >= 20 && (p) <= 23) || (p) == 25 || (p) == 32)
#define digitalPinToInterrupt(p) ((p) < NUM_DIGITAL_PINS ? (p) : -1)
#elif defined(__MKL26Z64__)
#define analogInputToDigitalPin(p) (((p) <= 9) ? (p) + 14 : (((p) <= 12) ? (p) + 14 : -1))
#define digitalPinHasPWM(p) ((p) == 3 || (p) == 4 || (p) == 6 || (p) == 9 || (p) == 10 || (p) <= 16 || (p) == 17 || (p) == 20 || (p) == 22 || (p) == 23)
#define digitalPinToInterrupt(p) ((((p) >= 2 && (p) <= 15) || ((p) >= 20 && (p) <= 23)) ? (p) : -1)
#endif


#if defined(KINETISK)
struct digital_pin_bitband_and_config_table_struct {
volatile uint32_t *reg;
volatile uint32_t *config;
};
extern const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[];

// compatibility macros
#define digitalPinToPort(pin) (pin)
#define digitalPinToBitMask(pin) (1)
@@ -91,11 +114,32 @@ extern const struct digital_pin_bitband_and_config_table_struct digital_pin_to_i
#define portInputRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 128))
#define portModeRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 160))
#define portConfigRegister(pin) ((volatile uint32_t *)(digital_pin_to_info_PGM[(pin)].config))


#define digitalPinToPortReg(pin) (portOutputRegister(pin))
#define digitalPinToBit(pin) (1)

#elif defined(KINETISL)
struct digital_pin_bitband_and_config_table_struct {
volatile uint8_t *reg;
volatile uint32_t *config;
uint8_t mask;
};
extern const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[];
// compatibility macros
#define digitalPinToPort(pin) (pin)
#define digitalPinToBitMask(pin) (digital_pin_to_info_PGM[(pin)].mask)
#define portOutputRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 0))
#define portSetRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 4))
#define portClearRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 8))
#define portToggleRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 12))
#define portInputRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 16))
#define portModeRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 20))
#define portConfigRegister(pin) ((digital_pin_to_info_PGM[(pin)].config))
#define digitalPinToPortReg(pin) (portOutputRegister(pin))
//#define digitalPinToBit(pin) (1)

#endif



#define NOT_ON_TIMER 0
static inline uint8_t digitalPinToTimer(uint8_t) __attribute__((always_inline, unused));

+ 255
- 101
teensy3/pins_teensy.c View File

@@ -32,34 +32,12 @@
#include "pins_arduino.h"
#include "HardwareSerial.h"

#if 0
// moved to pins_arduino.h
struct digital_pin_bitband_and_config_table_struct {
volatile uint32_t *reg;
volatile uint32_t *config;
};
const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[];

// compatibility macros
#define digitalPinToPort(pin) (pin)
#define digitalPinToBitMask(pin) (1)
#define portOutputRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 0))
#define portSetRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 32))
#define portClearRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 64))
#define portToggleRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 96))
#define portInputRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 128))
#define portModeRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 160))
#define portConfigRegister(pin) ((volatile uint32_t *)(digital_pin_to_info_PGM[(pin)].config))
#endif

//#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )
//#define analogInPinToBit(P) (P)

#if defined(KINETISK)
#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000)
#define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)))
//#define GPIO_SET_BIT(reg, bit) (*GPIO_BITBAND_PTR((reg), (bit)) = 1)
//#define GPIO_CLR_BIT(reg, bit) (*GPIO_BITBAND_PTR((reg), (bit)) = 0)

const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[] = {
{GPIO_BITBAND_PTR(CORE_PIN0_PORTREG, CORE_PIN0_BIT), &CORE_PIN0_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN1_PORTREG, CORE_PIN1_BIT), &CORE_PIN1_CONFIG},
@@ -97,24 +75,52 @@ const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM
{GPIO_BITBAND_PTR(CORE_PIN33_PORTREG, CORE_PIN33_BIT), &CORE_PIN33_CONFIG}
};

#elif defined(KINETISL)
const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[] = {
{((volatile uint8_t *)&CORE_PIN0_PORTREG + (CORE_PIN0_BIT >> 3)), &CORE_PIN0_CONFIG, (1<<(CORE_PIN0_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN1_PORTREG + (CORE_PIN1_BIT >> 3)), &CORE_PIN1_CONFIG, (1<<(CORE_PIN1_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN2_PORTREG + (CORE_PIN2_BIT >> 3)), &CORE_PIN2_CONFIG, (1<<(CORE_PIN2_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN3_PORTREG + (CORE_PIN3_BIT >> 3)), &CORE_PIN3_CONFIG, (1<<(CORE_PIN3_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN4_PORTREG + (CORE_PIN4_BIT >> 3)), &CORE_PIN4_CONFIG, (1<<(CORE_PIN4_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN5_PORTREG + (CORE_PIN5_BIT >> 3)), &CORE_PIN5_CONFIG, (1<<(CORE_PIN5_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN6_PORTREG + (CORE_PIN6_BIT >> 3)), &CORE_PIN6_CONFIG, (1<<(CORE_PIN6_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN7_PORTREG + (CORE_PIN7_BIT >> 3)), &CORE_PIN7_CONFIG, (1<<(CORE_PIN7_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN8_PORTREG + (CORE_PIN8_BIT >> 3)), &CORE_PIN8_CONFIG, (1<<(CORE_PIN8_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN9_PORTREG + (CORE_PIN9_BIT >> 3)), &CORE_PIN9_CONFIG, (1<<(CORE_PIN9_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN10_PORTREG + (CORE_PIN10_BIT >> 3)), &CORE_PIN10_CONFIG, (1<<(CORE_PIN10_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN11_PORTREG + (CORE_PIN11_BIT >> 3)), &CORE_PIN11_CONFIG, (1<<(CORE_PIN11_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN12_PORTREG + (CORE_PIN12_BIT >> 3)), &CORE_PIN12_CONFIG, (1<<(CORE_PIN12_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN13_PORTREG + (CORE_PIN13_BIT >> 3)), &CORE_PIN13_CONFIG, (1<<(CORE_PIN13_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN14_PORTREG + (CORE_PIN14_BIT >> 3)), &CORE_PIN14_CONFIG, (1<<(CORE_PIN14_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN15_PORTREG + (CORE_PIN15_BIT >> 3)), &CORE_PIN15_CONFIG, (1<<(CORE_PIN15_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN16_PORTREG + (CORE_PIN16_BIT >> 3)), &CORE_PIN16_CONFIG, (1<<(CORE_PIN16_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN17_PORTREG + (CORE_PIN17_BIT >> 3)), &CORE_PIN17_CONFIG, (1<<(CORE_PIN17_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN18_PORTREG + (CORE_PIN18_BIT >> 3)), &CORE_PIN18_CONFIG, (1<<(CORE_PIN18_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN19_PORTREG + (CORE_PIN19_BIT >> 3)), &CORE_PIN19_CONFIG, (1<<(CORE_PIN19_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN20_PORTREG + (CORE_PIN20_BIT >> 3)), &CORE_PIN20_CONFIG, (1<<(CORE_PIN20_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN21_PORTREG + (CORE_PIN21_BIT >> 3)), &CORE_PIN21_CONFIG, (1<<(CORE_PIN21_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN22_PORTREG + (CORE_PIN22_BIT >> 3)), &CORE_PIN22_CONFIG, (1<<(CORE_PIN22_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN23_PORTREG + (CORE_PIN23_BIT >> 3)), &CORE_PIN23_CONFIG, (1<<(CORE_PIN23_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN24_PORTREG + (CORE_PIN24_BIT >> 3)), &CORE_PIN24_CONFIG, (1<<(CORE_PIN24_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN25_PORTREG + (CORE_PIN25_BIT >> 3)), &CORE_PIN25_CONFIG, (1<<(CORE_PIN25_BIT & 7))},
{((volatile uint8_t *)&CORE_PIN26_PORTREG + (CORE_PIN26_BIT >> 3)), &CORE_PIN26_CONFIG, (1<<(CORE_PIN26_BIT & 7))}
};

#endif


typedef void (*voidFuncPtr)(void);
volatile static voidFuncPtr intFunc[CORE_NUM_DIGITAL];

void init_pin_interrupts(void)
{
//SIM_SCGC5 = 0x00043F82; // clocks active to all GPIO
NVIC_ENABLE_IRQ(IRQ_PORTA);
NVIC_ENABLE_IRQ(IRQ_PORTB);
NVIC_ENABLE_IRQ(IRQ_PORTC);
NVIC_ENABLE_IRQ(IRQ_PORTD);
NVIC_ENABLE_IRQ(IRQ_PORTE);
// TODO: maybe these should be set to a lower priority
// so if the user puts lots of slow code on attachInterrupt
// fast interrupts will still be serviced quickly?
}
#if defined(KINETISK)
static void porta_interrupt(void);
static void portb_interrupt(void);
static void portc_interrupt(void);
static void portd_interrupt(void);
static void porte_interrupt(void);
#elif defined(KINETISL)
static void porta_interrupt(void);
static void portcd_interrupt(void);
#endif

void attachInterruptVector(enum IRQ_NUMBER_t irq, void (*function)(void))
{
@@ -138,6 +144,16 @@ void attachInterrupt(uint8_t pin, void (*function)(void), int mode)
mask = (mask << 16) | 0x01000000;
config = portConfigRegister(pin);

#if defined(KINETISK)
attachInterruptVector(IRQ_PORTA, porta_interrupt);
attachInterruptVector(IRQ_PORTB, portb_interrupt);
attachInterruptVector(IRQ_PORTC, portc_interrupt);
attachInterruptVector(IRQ_PORTD, portd_interrupt);
attachInterruptVector(IRQ_PORTE, porte_interrupt);
#elif defined(KINETISL)
attachInterruptVector(IRQ_PORTA, porta_interrupt);
attachInterruptVector(IRQ_PORTCD, portcd_interrupt);
#endif
__disable_irq();
cfg = *config;
cfg &= ~0x000F0000; // disable any previous interrupt
@@ -159,8 +175,9 @@ void detachInterrupt(uint8_t pin)
__enable_irq();
}

#if defined(__MK20DX128__) || defined(__MK20DX256__)

void porta_isr(void)
static void porta_interrupt(void)
{
uint32_t isfr = PORTA_ISFR;
PORTA_ISFR = isfr;
@@ -170,7 +187,7 @@ void porta_isr(void)
if ((isfr & CORE_PIN33_BITMASK) && intFunc[33]) intFunc[33]();
}

void portb_isr(void)
static void portb_interrupt(void)
{
uint32_t isfr = PORTB_ISFR;
PORTB_ISFR = isfr;
@@ -184,7 +201,7 @@ void portb_isr(void)
if ((isfr & CORE_PIN32_BITMASK) && intFunc[32]) intFunc[32]();
}

void portc_isr(void)
static void portc_interrupt(void)
{
// TODO: these are inefficent. Use CLZ somehow....
uint32_t isfr = PORTC_ISFR;
@@ -203,7 +220,7 @@ void portc_isr(void)
if ((isfr & CORE_PIN30_BITMASK) && intFunc[30]) intFunc[30]();
}

void portd_isr(void)
static void portd_interrupt(void)
{
uint32_t isfr = PORTD_ISFR;
PORTD_ISFR = isfr;
@@ -217,7 +234,7 @@ void portd_isr(void)
if ((isfr & CORE_PIN21_BITMASK) && intFunc[21]) intFunc[21]();
}

void porte_isr(void)
static void porte_interrupt(void)
{
uint32_t isfr = PORTE_ISFR;
PORTE_ISFR = isfr;
@@ -225,7 +242,41 @@ void porte_isr(void)
if ((isfr & CORE_PIN31_BITMASK) && intFunc[31]) intFunc[31]();
}

#elif defined(__MKL26Z64__)

static void porta_interrupt(void)
{
uint32_t isfr = PORTA_ISFR;
PORTA_ISFR = isfr;
if ((isfr & CORE_PIN3_BITMASK) && intFunc[3]) intFunc[3]();
if ((isfr & CORE_PIN4_BITMASK) && intFunc[4]) intFunc[4]();
}

static void portcd_interrupt(void)
{
uint32_t isfr = PORTC_ISFR;
PORTC_ISFR = isfr;
if ((isfr & CORE_PIN9_BITMASK) && intFunc[9]) intFunc[9]();
if ((isfr & CORE_PIN10_BITMASK) && intFunc[10]) intFunc[10]();
if ((isfr & CORE_PIN11_BITMASK) && intFunc[11]) intFunc[11]();
if ((isfr & CORE_PIN12_BITMASK) && intFunc[12]) intFunc[12]();
if ((isfr & CORE_PIN13_BITMASK) && intFunc[13]) intFunc[13]();
if ((isfr & CORE_PIN15_BITMASK) && intFunc[15]) intFunc[15]();
if ((isfr & CORE_PIN22_BITMASK) && intFunc[22]) intFunc[22]();
if ((isfr & CORE_PIN23_BITMASK) && intFunc[23]) intFunc[23]();
isfr = PORTD_ISFR;
PORTD_ISFR = isfr;
if ((isfr & CORE_PIN2_BITMASK) && intFunc[2]) intFunc[2]();
if ((isfr & CORE_PIN5_BITMASK) && intFunc[5]) intFunc[5]();
if ((isfr & CORE_PIN6_BITMASK) && intFunc[6]) intFunc[6]();
if ((isfr & CORE_PIN7_BITMASK) && intFunc[7]) intFunc[7]();
if ((isfr & CORE_PIN8_BITMASK) && intFunc[8]) intFunc[8]();
if ((isfr & CORE_PIN14_BITMASK) && intFunc[14]) intFunc[14]();
if ((isfr & CORE_PIN20_BITMASK) && intFunc[20]) intFunc[20]();
if ((isfr & CORE_PIN21_BITMASK) && intFunc[21]) intFunc[21]();
}

#endif


unsigned long rtc_get(void)
@@ -326,34 +377,40 @@ extern void usb_init(void);

// create a default PWM at the same 488.28 Hz as Arduino Uno

#if F_BUS == 60000000
#if defined(KINETISK)
#define F_TIMER F_BUS
#elif defined(KINETISL)
#define F_TIMER (F_PLL/2)
#endif

#if F_TIMER == 60000000
#define DEFAULT_FTM_MOD (61440 - 1)
#define DEFAULT_FTM_PRESCALE 1
#elif F_BUS == 56000000
#elif F_TIMER == 56000000
#define DEFAULT_FTM_MOD (57344 - 1)
#define DEFAULT_FTM_PRESCALE 1
#elif F_BUS == 48000000
#elif F_TIMER == 48000000
#define DEFAULT_FTM_MOD (49152 - 1)
#define DEFAULT_FTM_PRESCALE 1
#elif F_BUS == 40000000
#elif F_TIMER == 40000000
#define DEFAULT_FTM_MOD (40960 - 1)
#define DEFAULT_FTM_PRESCALE 1
#elif F_BUS == 36000000
#elif F_TIMER == 36000000
#define DEFAULT_FTM_MOD (36864 - 1)
#define DEFAULT_FTM_PRESCALE 1
#elif F_BUS == 24000000
#elif F_TIMER == 24000000
#define DEFAULT_FTM_MOD (49152 - 1)
#define DEFAULT_FTM_PRESCALE 0
#elif F_BUS == 16000000
#elif F_TIMER == 16000000
#define DEFAULT_FTM_MOD (32768 - 1)
#define DEFAULT_FTM_PRESCALE 0
#elif F_BUS == 8000000
#elif F_TIMER == 8000000
#define DEFAULT_FTM_MOD (16384 - 1)
#define DEFAULT_FTM_PRESCALE 0
#elif F_BUS == 4000000
#elif F_TIMER == 4000000
#define DEFAULT_FTM_MOD (8192 - 1)
#define DEFAULT_FTM_PRESCALE 0
#elif F_BUS == 2000000
#elif F_TIMER == 2000000
#define DEFAULT_FTM_MOD (4096 - 1)
#define DEFAULT_FTM_PRESCALE 0
#endif
@@ -361,8 +418,16 @@ extern void usb_init(void);
//void init_pins(void)
void _init_Teensyduino_internal_(void)
{
init_pin_interrupts();

#if defined(__MK20DX128__) || defined(__MK20DX256__)
NVIC_ENABLE_IRQ(IRQ_PORTA);
NVIC_ENABLE_IRQ(IRQ_PORTB);
NVIC_ENABLE_IRQ(IRQ_PORTC);
NVIC_ENABLE_IRQ(IRQ_PORTD);
NVIC_ENABLE_IRQ(IRQ_PORTE);
#elif defined(__MKL26Z64__)
NVIC_ENABLE_IRQ(IRQ_PORTA);
NVIC_ENABLE_IRQ(IRQ_PORTCD);
#endif
//SIM_SCGC6 |= SIM_SCGC6_FTM0; // TODO: use bitband for atomic read-mod-write
//SIM_SCGC6 |= SIM_SCGC6_FTM1;
FTM0_CNT = 0;
@@ -373,22 +438,23 @@ void _init_Teensyduino_internal_(void)
FTM0_C3SC = 0x28;
FTM0_C4SC = 0x28;
FTM0_C5SC = 0x28;
#if defined(__MK20DX128__) || defined(__MK20DX256__)
FTM0_C6SC = 0x28;
FTM0_C7SC = 0x28;
#endif
FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(DEFAULT_FTM_PRESCALE);
FTM1_CNT = 0;
FTM1_MOD = DEFAULT_FTM_MOD;
FTM1_C0SC = 0x28;
FTM1_C1SC = 0x28;
FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(DEFAULT_FTM_PRESCALE);
#if defined(__MK20DX256__)
#if defined(__MK20DX256__) || defined(__MKL26Z64__)
FTM2_CNT = 0;
FTM2_MOD = DEFAULT_FTM_MOD;
FTM2_C0SC = 0x28;
FTM2_C1SC = 0x28;
FTM2_SC = FTM_SC_CLKS(1) | FTM_SC_PS(DEFAULT_FTM_PRESCALE);
#endif

analog_init();
//delay(100); // TODO: this is not necessary, right?
delay(4);
@@ -396,6 +462,44 @@ void _init_Teensyduino_internal_(void)
}


#if defined(__MK20DX128__)
#define FTM0_CH0_PIN 22
#define FTM0_CH1_PIN 23
#define FTM0_CH2_PIN 9
#define FTM0_CH3_PIN 10
#define FTM0_CH4_PIN 6
#define FTM0_CH5_PIN 20
#define FTM0_CH6_PIN 21
#define FTM0_CH7_PIN 5
#define FTM1_CH0_PIN 3
#define FTM1_CH1_PIN 4
#elif defined(__MK20DX256__)
#define FTM0_CH0_PIN 22
#define FTM0_CH1_PIN 23
#define FTM0_CH2_PIN 9
#define FTM0_CH3_PIN 10
#define FTM0_CH4_PIN 6
#define FTM0_CH5_PIN 20
#define FTM0_CH6_PIN 21
#define FTM0_CH7_PIN 5
#define FTM1_CH0_PIN 3
#define FTM1_CH1_PIN 4
#define FTM2_CH0_PIN 32
#define FTM2_CH1_PIN 25
#elif defined(__MKL26Z64__)
#define FTM0_CH0_PIN 22
#define FTM0_CH1_PIN 23
#define FTM0_CH2_PIN 9
#define FTM0_CH3_PIN 10
#define FTM0_CH4_PIN 6
#define FTM0_CH5_PIN 20
#define FTM1_CH0_PIN 16
#define FTM1_CH1_PIN 17
#define FTM2_CH0_PIN 3
#define FTM2_CH1_PIN 4
#endif
#define FTM_PINCFG(pin) FTM_PINCFG2(pin)
#define FTM_PINCFG2(pin) CORE_PIN ## pin ## _CONFIG

static uint8_t analog_write_res = 8;

@@ -439,10 +543,10 @@ void analogWrite(uint8_t pin, int val)
//serial_print("analog_write_res = ");
//serial_phex(analog_write_res);
//serial_print("\n");
if (pin == 3 || pin == 4) {
if (pin == FTM1_CH0_PIN || pin == FTM1_CH1_PIN) {
cval = ((uint32_t)val * (uint32_t)(FTM1_MOD + 1)) >> analog_write_res;
#if defined(__MK20DX256__)
} else if (pin == 25 || pin == 32) {
#if defined(FTM2_CH0_PIN)
} else if (pin == FTM2_CH0_PIN || pin == FTM2_CH1_PIN) {
cval = ((uint32_t)val * (uint32_t)(FTM2_MOD + 1)) >> analog_write_res;
#endif
} else {
@@ -452,54 +556,76 @@ void analogWrite(uint8_t pin, int val)
//serial_phex32(cval);
//serial_print("\n");
switch (pin) {
case 3: // PTA12, FTM1_CH0
FTM1_C0V = cval;
CORE_PIN3_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
case 4: // PTA13, FTM1_CH1
FTM1_C1V = cval;
CORE_PIN4_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
case 5: // PTD7, FTM0_CH7
FTM0_C7V = cval;
CORE_PIN5_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
#ifdef FTM0_CH0_PIN
case FTM0_CH0_PIN: // PTC1, FTM0_CH0
FTM0_C0V = cval;
FTM_PINCFG(FTM0_CH0_PIN) = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
case 6: // PTD4, FTM0_CH4
FTM0_C4V = cval;
CORE_PIN6_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
#endif
#ifdef FTM0_CH1_PIN
case FTM0_CH1_PIN: // PTC2, FTM0_CH1
FTM0_C1V = cval;
FTM_PINCFG(FTM0_CH1_PIN) = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
case 9: // PTC3, FTM0_CH2
#endif
#ifdef FTM0_CH2_PIN
case FTM0_CH2_PIN: // PTC3, FTM0_CH2
FTM0_C2V = cval;
CORE_PIN9_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
FTM_PINCFG(FTM0_CH2_PIN) = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
case 10: // PTC4, FTM0_CH3
#endif
#ifdef FTM0_CH3_PIN
case FTM0_CH3_PIN: // PTC4, FTM0_CH3
FTM0_C3V = cval;
CORE_PIN10_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
FTM_PINCFG(FTM0_CH3_PIN) = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
#endif
#ifdef FTM0_CH4_PIN
case FTM0_CH4_PIN: // PTD4, FTM0_CH4
FTM0_C4V = cval;
FTM_PINCFG(FTM0_CH4_PIN) = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
case 20: // PTD5, FTM0_CH5
#endif
#ifdef FTM0_CH5_PIN
case FTM0_CH5_PIN: // PTD5, FTM0_CH5
FTM0_C5V = cval;
CORE_PIN20_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
FTM_PINCFG(FTM0_CH5_PIN) = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
case 21: // PTD6, FTM0_CH6
#endif
#ifdef FTM0_CH6_PIN
case FTM0_CH6_PIN: // PTD6, FTM0_CH6
FTM0_C6V = cval;
CORE_PIN21_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
FTM_PINCFG(FTM0_CH6_PIN) = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
case 22: // PTC1, FTM0_CH0
FTM0_C0V = cval;
CORE_PIN22_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
#endif
#ifdef FTM0_CH7_PIN
case FTM0_CH7_PIN: // PTD7, FTM0_CH7
FTM0_C7V = cval;
FTM_PINCFG(FTM0_CH7_PIN) = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
case 23: // PTC2, FTM0_CH1
FTM0_C1V = cval;
CORE_PIN23_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
#endif
#ifdef FTM1_CH0_PIN
case FTM1_CH0_PIN: // PTA12, FTM1_CH0
FTM1_C0V = cval;
FTM_PINCFG(FTM1_CH0_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
#if defined(__MK20DX256__)
case 32: // PTB18, FTM2_CH0
#endif
#ifdef FTM1_CH1_PIN
case FTM1_CH1_PIN: // PTA13, FTM1_CH1
FTM1_C1V = cval;
FTM_PINCFG(FTM1_CH1_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
#endif
#ifdef FTM2_CH0_PIN
case FTM2_CH0_PIN: // PTB18, FTM2_CH0
FTM2_C0V = cval;
CORE_PIN32_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
FTM_PINCFG(FTM2_CH0_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
case 25: // PTB19, FTM1_CH1
#endif
#ifdef FTM2_CH1_PIN
case FTM2_CH1_PIN: // PTB19, FTM1_CH1
FTM2_C1V = cval;
CORE_PIN25_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
FTM_PINCFG(FTM2_CH1_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
#endif
default:
@@ -508,6 +634,7 @@ void analogWrite(uint8_t pin, int val)
}
}


void analogWriteRes(uint32_t bits)
{
if (bits < 1) {
@@ -518,6 +645,7 @@ void analogWriteRes(uint32_t bits)
analog_write_res = bits;
}


void analogWriteFrequency(uint8_t pin, uint32_t frequency)
{
uint32_t minfreq, prescale, mod;
@@ -528,35 +656,40 @@ void analogWriteFrequency(uint8_t pin, uint32_t frequency)
//serial_phex32(frequency);
//serial_print("\n");
for (prescale = 0; prescale < 7; prescale++) {
minfreq = (F_BUS >> 16) >> prescale;
minfreq = (F_TIMER >> 16) >> prescale;
if (frequency > minfreq) break;
}
//serial_print("F_BUS = ");
//serial_phex32(F_BUS >> prescale);
//serial_print("F_TIMER = ");
//serial_phex32(F_TIMER >> prescale);
//serial_print("\n");
//serial_print("prescale = ");
//serial_phex(prescale);
//serial_print("\n");
//mod = ((F_BUS >> prescale) / frequency) - 1;
mod = (((F_BUS >> prescale) + (frequency >> 1)) / frequency) - 1;
//mod = ((F_TIMER >> prescale) / frequency) - 1;
mod = (((F_TIMER >> prescale) + (frequency >> 1)) / frequency) - 1;
if (mod > 65535) mod = 65535;
//serial_print("mod = ");
//serial_phex32(mod);
//serial_print("\n");
if (pin == 3 || pin == 4) {
if (pin == FTM1_CH0_PIN || pin == FTM1_CH1_PIN) {
FTM1_SC = 0;
FTM1_CNT = 0;
FTM1_MOD = mod;
FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(prescale);
} else if (pin == 5 || pin == 6 || pin == 9 || pin == 10 ||
(pin >= 20 && pin <= 23)) {
} else if (pin == FTM0_CH0_PIN || pin == FTM0_CH1_PIN
|| pin == FTM0_CH2_PIN || pin == FTM0_CH3_PIN
|| pin == FTM0_CH4_PIN || pin == FTM0_CH5_PIN
#ifdef FTM0_CH6_PIN
|| pin == FTM0_CH6_PIN || pin == FTM0_CH7_PIN
#endif
) {
FTM0_SC = 0;
FTM0_CNT = 0;
FTM0_MOD = mod;
FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(prescale);
}
#if defined(__MK20DX256__)
else if (pin == 25 || pin == 32) {
#ifdef FTM2_CH0_PIN
else if (pin == FTM2_CH0_PIN || pin == FTM2_CH1_PIN) {
FTM2_SC = 0;
FTM2_CNT = 0;
FTM2_MOD = mod;
@@ -572,12 +705,21 @@ void analogWriteFrequency(uint8_t pin, uint32_t frequency)
void digitalWrite(uint8_t pin, uint8_t val)
{
if (pin >= CORE_NUM_DIGITAL) return;
#ifdef KINETISK
if (*portModeRegister(pin)) {
if (val) {
*portSetRegister(pin) = 1;
} else {
*portClearRegister(pin) = 1;
}
#else
if (*portModeRegister(pin) & digitalPinToBitMask(pin)) {
if (val) {
*portSetRegister(pin) = digitalPinToBitMask(pin);
} else {
*portClearRegister(pin) = digitalPinToBitMask(pin);
}
#endif
} else {
volatile uint32_t *config = portConfigRegister(pin);
if (val) {
@@ -596,7 +738,11 @@ void digitalWrite(uint8_t pin, uint8_t val)
uint8_t digitalRead(uint8_t pin)
{
if (pin >= CORE_NUM_DIGITAL) return 0;
#ifdef KINETISK
return *portInputRegister(pin);
#else
return (*portInputRegister(pin) & digitalPinToBitMask(pin)) ? 1 : 0;
#endif
}


@@ -609,10 +755,18 @@ void pinMode(uint8_t pin, uint8_t mode)
config = portConfigRegister(pin);

if (mode == OUTPUT) {
#ifdef KINETISK
*portModeRegister(pin) = 1;
#else
*portModeRegister(pin) |= digitalPinToBitMask(pin); // TODO: atomic
#endif
*config = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
} else {
#ifdef KINETISK
*portModeRegister(pin) = 0;
#else
*portModeRegister(pin) &= ~digitalPinToBitMask(pin);
#endif
if (mode == INPUT) {
*config = PORT_PCR_MUX(1);
} else {

+ 49
- 0
teensy3/ser_print.c View File

@@ -0,0 +1,49 @@
#include "kinetis.h"
#include "ser_print.h"

#ifdef KINETISL

// Simple polling-only Serial1 support for Teensy-LC

// this is really only useful for extremely low-level troubleshooting

void ser_write(uint8_t c)
{
while ((UART0_S1 & UART_S1_TDRE) == 0) /* wait */ ;
UART0_D = c;
}

void ser_print(const char *p)
{
while (*p) {
char c = *p++;
if (c == '\n') ser_write('\r');
ser_write(c);
}
}

static void ser_print_hex1(unsigned int n)
{
n &= 15;
if (n < 10) {
ser_write('0' + n);
} else {
ser_write('A' - 10 + n);
}
}

void ser_print_hex(unsigned int n)
{
ser_print_hex1(n >> 4);
ser_print_hex1(n);
}

void ser_print_hex32(unsigned int n)
{
ser_print_hex(n >> 24);
ser_print_hex(n >> 16);
ser_print_hex(n >> 8);
ser_print_hex(n);
}

#endif

+ 11
- 0
teensy3/ser_print.h View File

@@ -0,0 +1,11 @@

#ifdef __cplusplus
extern "C"{
#endif
void ser_print(const char *p);
void ser_print_hex(unsigned int n);
void ser_print_hex32(unsigned int n);
#ifdef __cplusplus
} // extern "C"
#endif


+ 56
- 3
teensy3/serial1.c View File

@@ -75,7 +75,11 @@ static volatile uint8_t rx_buffer_tail = 0;
// UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS
// UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer

#ifdef KINETISK_UART0_FIFO
#define C2_ENABLE UART_C2_TE | UART_C2_RE | UART_C2_RIE | UART_C2_ILIE
#else
#define C2_ENABLE UART_C2_TE | UART_C2_RE | UART_C2_RIE
#endif
#define C2_TX_ACTIVE C2_ENABLE | UART_C2_TIE
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE
@@ -90,14 +94,24 @@ void serial_begin(uint32_t divisor)
transmitting = 0;
CORE_PIN0_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3);
CORE_PIN1_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
#if defined(KINETISK_UART0)
UART0_BDH = (divisor >> 13) & 0x1F;
UART0_BDL = (divisor >> 5) & 0xFF;
UART0_C4 = divisor & 0x1F;
//UART0_C1 = 0;
#ifdef KINETISK_UART0_FIFO
UART0_C1 = UART_C1_ILT;
UART0_TWFIFO = 2; // tx watermark, causes S1_TDRE to set
UART0_RWFIFO = 4; // rx watermark, causes S1_RDRF to set
UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
#else
UART0_C1 = 0;
UART0_PFIFO = 0;
#endif
#elif defined(KINETISL_UART1)
UART0_BDH = (divisor >> 8) & 0x1F;
UART0_BDL = divisor & 0xFF;
UART0_C1 = 0;
#endif
UART0_C2 = C2_TX_INACTIVE;
NVIC_SET_PRIORITY(IRQ_UART0_STATUS, IRQ_PRIORITY);
NVIC_ENABLE_IRQ(IRQ_UART0_STATUS);
@@ -175,6 +189,7 @@ void serial_putchar(uint32_t c)
UART0_C2 = C2_TX_ACTIVE;
}

#ifdef KINETISK_UART0_FIFO
void serial_write(const void *buf, unsigned int count)
{
const uint8_t *p = (const uint8_t *)buf;
@@ -210,6 +225,13 @@ void serial_write(const void *buf, unsigned int count)
}
UART0_C2 = C2_TX_ACTIVE;
}
#else
void serial_write(const void *buf, unsigned int count)
{
const uint8_t *p = (const uint8_t *)buf;
while (count-- > 0) serial_putchar(*p++);
}
#endif

void serial_flush(void)
{
@@ -263,10 +285,12 @@ int serial_peek(void)

void serial_clear(void)
{
#ifdef KINETISK_UART0_FIFO
if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
UART0_C2 &= ~(UART_C2_RE | UART_C2_RIE | UART_C2_ILIE);
UART0_CFIFO = UART_CFIFO_RXFLUSH;
UART0_C2 |= (UART_C2_RE | UART_C2_RIE | UART_C2_ILIE);
#endif
rx_buffer_head = rx_buffer_tail;
}

@@ -280,8 +304,11 @@ void serial_clear(void)

void uart0_status_isr(void)
{
uint32_t head, newhead, tail, n;
uint8_t avail, c;
uint32_t head, tail, n;
uint8_t c;
#ifdef KINETISK_UART0_FIFO
uint32_t newhead;
uint8_t avail;

if (UART0_S1 & (UART_S1_RDRF | UART_S1_IDLE)) {
__disable_irq();
@@ -337,6 +364,32 @@ void uart0_status_isr(void)
tx_buffer_tail = tail;
if (UART0_S1 & UART_S1_TDRE) UART0_C2 = C2_TX_COMPLETING;
}
#else
if (UART0_S1 & UART_S1_RDRF) {
n = UART0_D;
if (use9Bits && (UART0_C3 & 0x80)) n |= 0x100;
head = rx_buffer_head + 1;
if (head >= RX_BUFFER_SIZE) head = 0;
if (head != rx_buffer_tail) {
rx_buffer[head] = n;
rx_buffer_head = head;
}
}
c = UART0_C2;
if ((c & UART_C2_TIE) && (UART0_S1 & UART_S1_TDRE)) {
head = tx_buffer_head;
tail = tx_buffer_tail;
if (head == tail) {
UART0_C2 = C2_TX_COMPLETING;
} else {
if (++tail >= TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART0_C3 = (UART0_C3 & ~0x40) | ((n & 0x100) >> 2);
UART0_D = n;
tx_buffer_tail = tail;
}
}
#endif
if ((c & UART_C2_TCIE) && (UART0_S1 & UART_S1_TC)) {
transmitting = 0;
if (transmit_pin) *transmit_pin = 0;

+ 6
- 0
teensy3/serial2.c View File

@@ -93,6 +93,7 @@ void serial2_begin(uint32_t divisor)
transmitting = 0;
CORE_PIN9_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3);
CORE_PIN10_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
#if defined(KINETISK_UART1)
UART1_BDH = (divisor >> 13) & 0x1F;
UART1_BDL = (divisor >> 5) & 0xFF;
UART1_C4 = divisor & 0x1F;
@@ -104,6 +105,11 @@ void serial2_begin(uint32_t divisor)
#else
UART1_C1 = 0;
UART1_PFIFO = 0;
#endif
#elif defined(KINETISL_UART1)
UART1_BDH = (divisor >> 8) & 0x1F;
UART1_BDL = divisor & 0xFF;
UART1_C1 = 0;
#endif
UART1_C2 = C2_TX_INACTIVE;
NVIC_SET_PRIORITY(IRQ_UART1_STATUS, IRQ_PRIORITY);

+ 6
- 0
teensy3/serial3.c View File

@@ -90,11 +90,17 @@ void serial3_begin(uint32_t divisor)
transmitting = 0;
CORE_PIN7_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3);
CORE_PIN8_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
#if defined(KINETISK_UART2)
UART2_BDH = (divisor >> 13) & 0x1F;
UART2_BDL = (divisor >> 5) & 0xFF;
UART2_C4 = divisor & 0x1F;
UART2_C1 = 0;
UART2_PFIFO = 0;
#elif defined(KINETISL_UART2)
UART2_BDH = (divisor >> 8) & 0x1F;
UART2_BDL = divisor & 0xFF;
UART2_C1 = 0;
#endif
UART2_C2 = C2_TX_INACTIVE;
NVIC_SET_PRIORITY(IRQ_UART2_STATUS, IRQ_PRIORITY);
NVIC_ENABLE_IRQ(IRQ_UART2_STATUS);

+ 29
- 7
teensy3/touch.c View File

@@ -31,6 +31,14 @@
#include "core_pins.h"
//#include "HardwareSerial.h"

#if defined(__MK20DX128__) || defined(__MK20DX256__)
// These settings give approx 0.02 pF sensitivity and 1200 pF range
// Lower current, higher number of scans, and higher prescaler
// increase sensitivity, but the trade-off is longer measurement
// time and decreased range.
#define CURRENT 2 // 0 to 15 - current to use, value is 2*(current+1)
#define NSCAN 9 // number of times to scan, 0 to 31, value is nscan+1
#define PRESCALE 2 // prescaler, 0 to 7 - value is 2^(prescaler+1)
static const uint8_t pin2tsi[] = {
//0 1 2 3 4 5 6 7 8 9
9, 10, 255, 255, 255, 255, 255, 255, 255, 255,
@@ -39,13 +47,17 @@ static const uint8_t pin2tsi[] = {
255, 255, 11, 5
};

// These settings give approx 0.02 pF sensitivity and 1200 pF range
// Lower current, higher number of scans, and higher prescaler
// increase sensitivity, but the trade-off is longer measurement
// time and decreased range.
#define CURRENT 2 // 0 to 15 - current to use, value is 2*(current+1)
#define NSCAN 9 // number of times to scan, 0 to 31, value is nscan+1
#define PRESCALE 2 // prescaler, 0 to 7 - value is 2^(prescaler+1)
#elif defined(__MKL26Z64__)
#define NSCAN 9
#define PRESCALE 2
static const uint8_t pin2tsi[] = {
//0 1 2 3 4 5 6 7 8 9
9, 10, 255, 2, 3, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 13, 0, 6, 8, 7,
255, 255, 14, 15, 255, 255, 255
};

#endif


// output is approx pF * 50
@@ -62,6 +74,7 @@ int touchRead(uint8_t pin)

*portConfigRegister(pin) = PORT_PCR_MUX(0);
SIM_SCGC5 |= SIM_SCGC5_TSI;
#if defined(KINETISK)
TSI0_GENCS = 0;
TSI0_PEN = (1 << ch);
TSI0_SCANC = TSI_SCANC_REFCHRG(3) | TSI_SCANC_EXTCHRG(CURRENT);
@@ -70,6 +83,15 @@ int touchRead(uint8_t pin)
while (TSI0_GENCS & TSI_GENCS_SCNIP) ; // wait
delayMicroseconds(1);
return *((volatile uint16_t *)(&TSI0_CNTR1) + ch);
#elif defined(KINETISL)
TSI0_GENCS = TSI_GENCS_REFCHRG(4) | TSI_GENCS_EXTCHRG(3) | TSI_GENCS_PS(PRESCALE)
| TSI_GENCS_NSCN(NSCAN) | TSI_GENCS_TSIEN | TSI_GENCS_EOSF;
TSI0_DATA = TSI_DATA_TSICH(ch) | TSI_DATA_SWTS;
delayMicroseconds(10);
while (TSI0_GENCS & TSI_GENCS_SCNIP) ; // wait
delayMicroseconds(1);
return TSI0_DATA & 0xFFFF;
#endif
}



+ 5
- 5
teensy3/usb_dev.c View File

@@ -715,7 +715,7 @@ void usb_isr(void)
restart:
status = USB0_ISTAT;

if ((status & USB_INTEN_SOFTOKEN /* 04 */ )) {
if ((status & USB_ISTAT_SOFTOK /* 04 */ )) {
if (usb_configuration) {
t = usb_reboot_timer;
if (t) {
@@ -743,7 +743,7 @@ void usb_isr(void)
usb_flightsim_flush_callback();
#endif
}
USB0_ISTAT = USB_INTEN_SOFTOKEN;
USB0_ISTAT = USB_ISTAT_SOFTOK;
}

if ((status & USB_ISTAT_TOKDNE /* 08 */ )) {
@@ -949,8 +949,8 @@ void usb_init(void)
SIM_SCGC4 |= SIM_SCGC4_USBOTG;

// reset USB module
USB0_USBTRC0 = USB_USBTRC_USBRESET;
while ((USB0_USBTRC0 & USB_USBTRC_USBRESET) != 0) ; // wait for reset to end
//USB0_USBTRC0 = USB_USBTRC_USBRESET;
//while ((USB0_USBTRC0 & USB_USBTRC_USBRESET) != 0) ; // wait for reset to end

// set desc table base addr
USB0_BDTPAGE1 = ((uint32_t)table) >> 8;
@@ -962,7 +962,7 @@ void usb_init(void)
USB0_ERRSTAT = 0xFF;
USB0_OTGISTAT = 0xFF;

USB0_USBTRC0 |= 0x40; // undocumented bit
//USB0_USBTRC0 |= 0x40; // undocumented bit

// enable USB
USB0_CTL = USB_CTL_USBENSOFEN;

Loading…
Cancel
Save