Browse Source

Support for Teensy 3.1

main
PaulStoffregen 11 years ago
parent
commit
729c211500
7 changed files with 1722 additions and 1036 deletions
  1. +173
    -39
      teensy3/analog.c
  2. +7
    -1
      teensy3/core_pins.h
  3. +193
    -52
      teensy3/mk20dx128.c
  4. +1158
    -936
      teensy3/mk20dx128.h
  5. +146
    -0
      teensy3/mk20dx256.ld
  6. +9
    -0
      teensy3/pins_arduino.h
  7. +36
    -8
      teensy3/pins_teensy.c

+ 173
- 39
teensy3/analog.c View File

@@ -42,13 +42,13 @@ static uint8_t analog_reference_internal = 0;
// datasheet says ADC clock should be 1 to 18 MHz for 8-12 bit mode

#if F_BUS == 48000000
#define ADC0_CFG1_6MHZ ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1)
#define ADC0_CFG1_12MHZ ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1)
#define ADC0_CFG1_24MHZ ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1)
#define ADC_CFG1_6MHZ ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1)
#define ADC_CFG1_12MHZ ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1)
#define ADC_CFG1_24MHZ ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1)
#elif F_BUS == 24000000
#define ADC0_CFG1_6MHZ ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(0)
#define ADC0_CFG1_12MHZ ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(0)
#define ADC0_CFG1_24MHZ ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0)
#define ADC_CFG1_6MHZ ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(0)
#define ADC_CFG1_12MHZ ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(0)
#define ADC_CFG1_24MHZ ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0)
#else
#error
#endif
@@ -61,36 +61,73 @@ void analog_init(void)
VREF_SC = 0xE1; // enable 1.2 volt ref

if (analog_config_bits == 8) {
ADC0_CFG1 = ADC0_CFG1_24MHZ + ADC_CFG1_MODE(0);
ADC0_CFG1 = ADC_CFG1_24MHZ + ADC_CFG1_MODE(0);
ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
#if defined(__MK20DX256__)
ADC1_CFG1 = ADC_CFG1_24MHZ + ADC_CFG1_MODE(0);
ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
#endif
} else if (analog_config_bits == 10) {
ADC0_CFG1 = ADC0_CFG1_12MHZ + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP;
ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP;
ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
#if defined(__MK20DX256__)
ADC1_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP;
ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
#endif
} else if (analog_config_bits == 12) {
ADC0_CFG1 = ADC0_CFG1_12MHZ + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP;
ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP;
ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
#if defined(__MK20DX256__)
ADC1_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP;
ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
#endif
} else {
ADC0_CFG1 = ADC0_CFG1_12MHZ + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP;
ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP;
ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
#if defined(__MK20DX256__)
ADC1_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP;
ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
#endif
}

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
}

num = analog_num_average;
if (num <= 1) {
ADC0_SC3 = ADC_SC3_CAL; // begin cal
#if defined(__MK20DX256__)
ADC1_SC3 = ADC_SC3_CAL; // begin cal
#endif
} else if (num <= 4) {
ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0);
#if defined(__MK20DX256__)
ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0);
#endif
} else if (num <= 8) {
ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1);
#if defined(__MK20DX256__)
ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1);
#endif
} else if (num <= 16) {
ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2);
#if defined(__MK20DX256__)
ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2);
#endif
} else {
ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3);
#if defined(__MK20DX256__)
ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3);
#endif
}
calibrating = 1;
}
@@ -100,10 +137,15 @@ static void wait_for_cal(void)
uint16_t sum;

//serial_print("wait_for_cal\n");
#if defined(__MK20DX128__)
while (ADC0_SC3 & ADC_SC3_CAL) {
// wait
//serial_print(".");
}
#elif defined(__MK20DX256__)
while ((ADC0_SC3 & ADC_SC3_CAL) || (ADC1_SC3 & ADC_SC3_CAL)) {
// wait
}
#endif
__disable_irq();
if (calibrating) {
//serial_print("\n");
@@ -119,6 +161,14 @@ static void wait_for_cal(void)
//serial_print("ADC0_MG = ");
//serial_phex16(sum);
//serial_print("\n");
#if defined(__MK20DX256__)
sum = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0;
sum = (sum / 2) | 0x8000;
ADC1_PG = sum;
sum = ADC1_CLMS + ADC1_CLM4 + ADC1_CLM3 + ADC1_CLM2 + ADC1_CLM1 + ADC1_CLM0;
sum = (sum / 2) | 0x8000;
ADC1_MG = sum;
#endif
calibrating = 0;
}
__enable_irq();
@@ -141,14 +191,24 @@ void analogReference(uint8_t type)
// internal reference requested
if (!analog_reference_internal) {
analog_reference_internal = 1;
if (calibrating) ADC0_SC3 = 0; // cancel cal
if (calibrating) {
ADC0_SC3 = 0; // cancel cal
#if defined(__MK20DX256__)
ADC1_SC3 = 0; // cancel cal
#endif
}
analog_init();
}
} else {
// vcc or external reference requested
if (analog_reference_internal) {
analog_reference_internal = 0;
if (calibrating) ADC0_SC3 = 0; // cancel cal
if (calibrating) {
ADC0_SC3 = 0; // cancel cal
#if defined(__MK20DX256__)
ADC1_SC3 = 0; // cancel cal
#endif
}
analog_init();
}
}
@@ -202,42 +262,83 @@ void analogReadAveraging(unsigned int num)

// The SC1A register is used for both software and hardware trigger modes of operation.


#if defined(__MK20DX128__)
static const uint8_t channel2sc1a[] = {
5, 14, 8, 9, 13, 12, 6, 7, 15, 4,
0, 19, 3, 21, 26, 22, 23
};
#elif defined(__MK20DX256__)
static const uint8_t channel2sc1a[] = {
5, 14, 8, 9, 13, 12, 6, 7, 15, 4,
0, 19, 3, 21, 26, 22
0, 19, 3, 19+128, 26, 22, 23,
5+192, 5+128, 4+128, 6+128, 7+128, 4+192
// A15 26 E1 ADC1_SE5a 5+64
// A16 27 C9 ADC1_SE5b 5
// A17 28 C8 ADC1_SE4b 4
// A18 29 C10 ADC1_SE6b 6
// A19 30 C11 ADC1_SE7b 7
// A20 31 E0 ADC1_SE4a 4+64
};
#endif



// TODO: perhaps this should store the NVIC priority, so it works recursively?
static volatile uint8_t analogReadBusy = 0;
static volatile uint8_t analogReadBusyADC0 = 0;
#if defined(__MK20DX256__)
static volatile uint8_t analogReadBusyADC1 = 0;
#endif

int analogRead(uint8_t pin)
{
int result;

if (pin >= 14) {
if (pin <= 23) {
pin -= 14; // 14-23 are A0-A9
} else if (pin >= 34 && pin <= 39) {
pin -= 24; // 34-37 are A10-A13, 38 is temp sensor, 39 is vref
} else {
return 0; // all others are invalid
}
uint8_t index, channel;

//serial_phex(pin);
//serial_print(" ");

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)
} else {
return 0; // all others are invalid
}

//serial_phex(index);
//serial_print(" ");

channel = channel2sc1a[index];
//serial_phex(channel);
//serial_print(" ");

//serial_print("analogRead");
//return 0;
if (calibrating) wait_for_cal();
//pin = 5; // PTD1/SE5b, pin 14, analog 0

#if defined(__MK20DX256__)
if (channel & 0x80) goto beginADC1;
#endif

__disable_irq();
start: ADC0_SC1A = channel2sc1a[pin];
analogReadBusy = 1;
startADC0:
//serial_print("startADC0\n");
ADC0_SC1A = channel;
analogReadBusyADC0 = 1;
__enable_irq();
while (1) {
__disable_irq();
if ((ADC0_SC1A & ADC_SC1_COCO)) {
result = ADC0_RA;
analogReadBusy = 0;
analogReadBusyADC0 = 0;
__enable_irq();
result >>= analog_right_shift;
return result;
@@ -245,27 +346,60 @@ start: ADC0_SC1A = channel2sc1a[pin];
// detect if analogRead was used from an interrupt
// if so, our analogRead got canceled, so it must
// be restarted.
if (!analogReadBusy) goto start;
if (!analogReadBusyADC0) goto startADC0;
__enable_irq();
yield();
}
#if 0
ADC0_SC1A = channel2sc1a[pin];
while ((ADC0_SC1A & ADC_SC1_COCO) == 0) {

#if defined(__MK20DX256__)
beginADC1:
__disable_irq();
startADC1:
//serial_print("startADC0\n");
// ADC1_CFG2[MUXSEL] bit selects between ADCx_SEn channels a and b.
if (channel & 0x40) {
ADC1_CFG2 &= ~ADC_CFG2_MUXSEL;
} else {
ADC1_CFG2 |= ADC_CFG2_MUXSEL;
}
ADC1_SC1A = channel & 0x3F;
analogReadBusyADC1 = 1;
__enable_irq();
while (1) {
__disable_irq();
if ((ADC1_SC1A & ADC_SC1_COCO)) {
result = ADC1_RA;
analogReadBusyADC1 = 0;
__enable_irq();
result >>= analog_right_shift;
return result;
}
// detect if analogRead was used from an interrupt
// if so, our analogRead got canceled, so it must
// be restarted.
if (!analogReadBusyADC1) goto startADC1;
__enable_irq();
yield();
// wait
//serial_print(".");
}
//serial_print("\n");
result = ADC0_RA >> analog_right_shift;
//serial_phex16(result >> 3);
//serial_print("\n");
return result;
#endif
}



void analogWriteDAC0(int val)
{
#if defined(__MK20DX256__)
SIM_SCGC2 |= SIM_SCGC2_DAC0;
if (analog_reference_internal) {
DAC0_C0 = DAC_C0_DACEN; // 1.2V ref is DACREF_1
} else {
DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2
}
if (val < 0) val = 0; // TODO: saturate instruction?
else if (val > 4095) val = 4095;
*(int16_t *)&(DAC0_DAT0L) = val;
#endif
}




+ 7
- 1
teensy3/core_pins.h View File

@@ -95,9 +95,14 @@

#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
#define CORE_NUM_INTERRUPT 34
#elif defined(__MK20DX256__)
#define CORE_NUM_ANALOG 21
#define CORE_NUM_PWM 12
#endif

#define CORE_PIN0_BIT 16
#define CORE_PIN1_BIT 17
@@ -687,6 +692,7 @@ void analogWrite(uint8_t pin, int val);
void analogWriteRes(uint32_t bits);
static inline void analogWriteResolution(uint32_t bits) { analogWriteRes(bits); }
void analogWriteFrequency(uint8_t pin, uint32_t frequency);
void analogWriteDAC0(int val);
void attachInterrupt(uint8_t pin, void (*function)(void), int mode);
void detachInterrupt(uint8_t pin);
void _init_Teensyduino_internal_(void);

+ 193
- 52
teensy3/mk20dx128.c View File

@@ -83,14 +83,38 @@ void dma_ch0_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_ch1_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_ch2_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_ch3_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_ch4_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_ch5_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_ch6_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_ch7_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_ch8_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_ch9_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_ch10_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_ch11_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_ch12_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_ch13_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_ch14_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_ch15_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_error_isr(void) __attribute__ ((weak, alias("unused_isr")));
void mcm_isr(void) __attribute__ ((weak, alias("unused_isr")));
void flash_cmd_isr(void) __attribute__ ((weak, alias("unused_isr")));
void flash_error_isr(void) __attribute__ ((weak, alias("unused_isr")));
void low_voltage_isr(void) __attribute__ ((weak, alias("unused_isr")));
void wakeup_isr(void) __attribute__ ((weak, alias("unused_isr")));
void watchdog_isr(void) __attribute__ ((weak, alias("unused_isr")));
void i2c0_isr(void) __attribute__ ((weak, alias("unused_isr")));
void i2c1_isr(void) __attribute__ ((weak, alias("unused_isr")));
void i2c2_isr(void) __attribute__ ((weak, alias("unused_isr")));
void spi0_isr(void) __attribute__ ((weak, alias("unused_isr")));
void spi1_isr(void) __attribute__ ((weak, alias("unused_isr")));
void spi2_isr(void) __attribute__ ((weak, alias("unused_isr")));
void sdhc_isr(void) __attribute__ ((weak, alias("unused_isr")));
void can0_message_isr(void) __attribute__ ((weak, alias("unused_isr")));
void can0_bus_off_isr(void) __attribute__ ((weak, alias("unused_isr")));
void can0_error_isr(void) __attribute__ ((weak, alias("unused_isr")));
void can0_tx_warn_isr(void) __attribute__ ((weak, alias("unused_isr")));
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 uart0_lon_isr(void) __attribute__ ((weak, alias("unused_isr")));
@@ -100,11 +124,21 @@ void uart1_status_isr(void) __attribute__ ((weak, alias("unused_isr")));
void uart1_error_isr(void) __attribute__ ((weak, alias("unused_isr")));
void uart2_status_isr(void) __attribute__ ((weak, alias("unused_isr")));
void uart2_error_isr(void) __attribute__ ((weak, alias("unused_isr")));
void uart3_status_isr(void) __attribute__ ((weak, alias("unused_isr")));
void uart3_error_isr(void) __attribute__ ((weak, alias("unused_isr")));
void uart4_status_isr(void) __attribute__ ((weak, alias("unused_isr")));
void uart4_error_isr(void) __attribute__ ((weak, alias("unused_isr")));
void uart5_status_isr(void) __attribute__ ((weak, alias("unused_isr")));
void uart5_error_isr(void) __attribute__ ((weak, alias("unused_isr")));
void adc0_isr(void) __attribute__ ((weak, alias("unused_isr")));
void adc1_isr(void) __attribute__ ((weak, alias("unused_isr")));
void cmp0_isr(void) __attribute__ ((weak, alias("unused_isr")));
void cmp1_isr(void) __attribute__ ((weak, alias("unused_isr")));
void cmp2_isr(void) __attribute__ ((weak, alias("unused_isr")));
void ftm0_isr(void) __attribute__ ((weak, alias("unused_isr")));
void ftm1_isr(void) __attribute__ ((weak, alias("unused_isr")));
void ftm2_isr(void) __attribute__ ((weak, alias("unused_isr")));
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")));
@@ -115,6 +149,8 @@ void pit3_isr(void) __attribute__ ((weak, alias("unused_isr")));
void pdb_isr(void) __attribute__ ((weak, alias("unused_isr")));
void usb_isr(void) __attribute__ ((weak, alias("unused_isr")));
void usb_charge_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dac0_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dac1_isr(void) __attribute__ ((weak, alias("unused_isr")));
void tsi0_isr(void) __attribute__ ((weak, alias("unused_isr")));
void mcg_isr(void) __attribute__ ((weak, alias("unused_isr")));
void lptmr_isr(void) __attribute__ ((weak, alias("unused_isr")));
@@ -131,8 +167,8 @@ void software_isr(void) __attribute__ ((weak, alias("unused_isr")));
__attribute__ ((section(".vectors"), used))
void (* const gVectors[])(void) =
{
(void (*)(void))((unsigned long)&_estack), // 0 ARM: Initial Stack Pointer
ResetHandler, // 1 ARM: Initial Program Counter
(void (*)(void))((unsigned long)&_estack), // 0 ARM: Initial Stack Pointer
ResetHandler, // 1 ARM: Initial Program Counter
nmi_isr, // 2 ARM: Non-maskable Interrupt (NMI)
hard_fault_isr, // 3 ARM: Hard Fault
memmanage_fault_isr, // 4 ARM: MemManage Fault
@@ -147,6 +183,7 @@ void (* const gVectors[])(void) =
fault_isr, // 13 --
pendablesrvreq_isr, // 14 ARM: Pendable req serv(PendableSrvReq)
systick_isr, // 15 ARM: System tick timer (SysTick)
#if defined(__MK20DX128__)
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
@@ -193,6 +230,103 @@ void (* const gVectors[])(void) =
portd_isr, // 59 Pin detect (Port D)
porte_isr, // 60 Pin detect (Port E)
software_isr, // 61 Software interrupt
#elif defined(__MK20DX256__)
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
dma_ch4_isr, // 20 DMA channel 4 transfer complete
dma_ch5_isr, // 21 DMA channel 5 transfer complete
dma_ch6_isr, // 22 DMA channel 6 transfer complete
dma_ch7_isr, // 23 DMA channel 7 transfer complete
dma_ch8_isr, // 24 DMA channel 8 transfer complete
dma_ch9_isr, // 25 DMA channel 9 transfer complete
dma_ch10_isr, // 26 DMA channel 10 transfer complete
dma_ch11_isr, // 27 DMA channel 10 transfer complete
dma_ch12_isr, // 28 DMA channel 10 transfer complete
dma_ch13_isr, // 29 DMA channel 10 transfer complete
dma_ch14_isr, // 30 DMA channel 10 transfer complete
dma_ch15_isr, // 31 DMA channel 10 transfer complete
dma_error_isr, // 32 DMA error interrupt channel
unused_isr, // 33 --
flash_cmd_isr, // 34 Flash Memory Command complete
flash_error_isr, // 35 Flash Read collision
low_voltage_isr, // 36 Low-voltage detect/warning
wakeup_isr, // 37 Low Leakage Wakeup
watchdog_isr, // 38 Both EWM and WDOG interrupt
unused_isr, // 39 --
i2c0_isr, // 40 I2C0
i2c1_isr, // 41 I2C1
spi0_isr, // 42 SPI0
spi1_isr, // 43 SPI1
unused_isr, // 44 --
can0_message_isr, // 45 CAN OR'ed Message buffer (0-15)
can0_bus_off_isr, // 46 CAN Bus Off
can0_error_isr, // 47 CAN Error
can0_tx_warn_isr, // 48 CAN Transmit Warning
can0_rx_warn_isr, // 49 CAN Receive Warning
can0_wakeup_isr, // 50 CAN Wake Up
i2s0_tx_isr, // 51 I2S0 Transmit
i2s0_rx_isr, // 52 I2S0 Receive
unused_isr, // 53 --
unused_isr, // 54 --
unused_isr, // 55 --
unused_isr, // 56 --
unused_isr, // 57 --
unused_isr, // 58 --
unused_isr, // 59 --
uart0_lon_isr, // 60 UART0 CEA709.1-B (LON) status
uart0_status_isr, // 61 UART0 status
uart0_error_isr, // 62 UART0 error
uart1_status_isr, // 63 UART1 status
uart1_error_isr, // 64 UART1 error
uart2_status_isr, // 65 UART2 status
uart2_error_isr, // 66 UART2 error
unused_isr, // 67 --
unused_isr, // 68 --
unused_isr, // 69 --
unused_isr, // 70 --
unused_isr, // 71 --
unused_isr, // 72 --
adc0_isr, // 73 ADC0
adc1_isr, // 74 ADC1
cmp0_isr, // 75 CMP0
cmp1_isr, // 76 CMP1
cmp2_isr, // 77 CMP2
ftm0_isr, // 78 FTM0
ftm1_isr, // 79 FTM1
ftm2_isr, // 80 FTM2
cmt_isr, // 81 CMT
rtc_alarm_isr, // 82 RTC Alarm interrupt
rtc_seconds_isr, // 83 RTC Seconds interrupt
pit0_isr, // 84 PIT Channel 0
pit1_isr, // 85 PIT Channel 1
pit2_isr, // 86 PIT Channel 2
pit3_isr, // 87 PIT Channel 3
pdb_isr, // 88 PDB Programmable Delay Block
usb_isr, // 89 USB OTG
usb_charge_isr, // 90 USB Charger Detect
unused_isr, // 91 --
unused_isr, // 92 --
unused_isr, // 93 --
unused_isr, // 94 --
unused_isr, // 95 --
unused_isr, // 96 --
dac0_isr, // 97 DAC0
unused_isr, // 98 --
tsi0_isr, // 99 TSI0
mcg_isr, // 100 MCG
lptmr_isr, // 101 Low Power Timer
unused_isr, // 102 --
porta_isr, // 103 Pin detect (Port A)
portb_isr, // 104 Pin detect (Port B)
portc_isr, // 105 Pin detect (Port C)
portd_isr, // 106 Pin detect (Port D)
porte_isr, // 107 Pin detect (Port E)
unused_isr, // 108 --
unused_isr, // 109 --
software_isr, // 110 Software interrupt
#endif
};

//void usb_isr(void)
@@ -224,8 +358,8 @@ void startup_late_hook(void) __attribute__ ((weak, alias("startup_unused_hook")
__attribute__ ((section(".startup")))
void ResetHandler(void)
{
uint32_t *src = &_etext;
uint32_t *dest = &_sdata;
uint32_t *src = &_etext;
uint32_t *dest = &_sdata;
unsigned int i;

WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
@@ -234,8 +368,15 @@ void ResetHandler(void)
startup_early_hook();

// enable clocks to always-used peripherals
#if defined(__MK20DX128__)
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(__MK20DX256__)
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;
#endif

// if the RTC oscillator isn't enabled, get it started early
if (!(RTC_CR & RTC_CR_OSCE)) {
RTC_SR = 0;
@@ -246,62 +387,62 @@ void ResetHandler(void)
if (PMC_REGSC & PMC_REGSC_ACKISO) PMC_REGSC |= PMC_REGSC_ACKISO;

// TODO: do this while the PLL is waiting to lock....
while (dest < &_edata) *dest++ = *src++;
dest = &_sbss;
while (dest < &_ebss) *dest++ = 0;
while (dest < &_edata) *dest++ = *src++;
dest = &_sbss;
while (dest < &_ebss) *dest++ = 0;
SCB_VTOR = 0; // use vector table in flash

// default all interrupts to medium priority level
for (i=0; i < NVIC_NUM_INTERRUPTS; i++) NVIC_SET_PRIORITY(i, 128);

// start in FEI mode
// enable capacitors for crystal
OSC0_CR = OSC_SC8P | OSC_SC2P;
// enable osc, 8-32 MHz range, low power mode
MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS;
// switch to crystal as clock source, FLL input = 16 MHz / 512
MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(4);
// wait for crystal oscillator to begin
while ((MCG_S & MCG_S_OSCINIT0) == 0) ;
// wait for FLL to use oscillator
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 we're in FBE mode
// config PLL input for 16 MHz Crystal / 4 = 4 MHz
MCG_C5 = MCG_C5_PRDIV0(3);
// config PLL for 96 MHz output
MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(0);
// wait for PLL to start using xtal as its input
while (!(MCG_S & MCG_S_PLLST)) ;
// wait for PLL to lock
while (!(MCG_S & MCG_S_LOCK0)) ;
// now we're in PBE mode
// start in FEI mode
// enable capacitors for crystal
OSC0_CR = OSC_SC8P | OSC_SC2P;
// enable osc, 8-32 MHz range, low power mode
MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS;
// switch to crystal as clock source, FLL input = 16 MHz / 512
MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(4);
// wait for crystal oscillator to begin
while ((MCG_S & MCG_S_OSCINIT0) == 0) ;
// wait for FLL to use oscillator
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 we're in FBE mode
// config PLL input for 16 MHz Crystal / 4 = 4 MHz
MCG_C5 = MCG_C5_PRDIV0(3);
// config PLL for 96 MHz output
MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(0);
// wait for PLL to start using xtal as its input
while (!(MCG_S & MCG_S_PLLST)) ;
// wait for PLL to lock
while (!(MCG_S & MCG_S_LOCK0)) ;
// now we're in PBE mode
#if F_CPU == 96000000
// config divisors: 96 MHz core, 48 MHz bus, 24 MHz flash
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(3);
// config divisors: 96 MHz core, 48 MHz bus, 24 MHz flash
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(3);
#elif F_CPU == 48000000
// config divisors: 48 MHz core, 48 MHz bus, 24 MHz flash
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(3);
// config divisors: 48 MHz core, 48 MHz bus, 24 MHz flash
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(3);
#elif F_CPU == 24000000
// config divisors: 24 MHz core, 24 MHz bus, 24 MHz flash
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV4(3);
// config divisors: 24 MHz core, 24 MHz bus, 24 MHz flash
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV4(3);
#else
#error "Error, F_CPU must be 96000000, 48000000, or 24000000"
#endif
// switch to PLL as clock source, FLL input = 16 MHz / 512
MCG_C1 = MCG_C1_CLKS(0) | MCG_C1_FRDIV(4);
// wait for PLL clock to be used
while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)) ;
// now we're in PEE mode
// configure USB for 48 MHz clock
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1); // USB = 96 MHz PLL / 2
// 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);
// initialize the SysTick counter
SYST_RVR = (F_CPU / 1000) - 1;
SYST_CSR = SYST_CSR_CLKSOURCE | SYST_CSR_TICKINT | SYST_CSR_ENABLE;
// switch to PLL as clock source, FLL input = 16 MHz / 512
MCG_C1 = MCG_C1_CLKS(0) | MCG_C1_FRDIV(4);
// wait for PLL clock to be used
while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)) ;
// now we're in PEE mode
// configure USB for 48 MHz clock
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1); // USB = 96 MHz PLL / 2
// 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);
// initialize the SysTick counter
SYST_RVR = (F_CPU / 1000) - 1;
SYST_CSR = SYST_CSR_CLKSOURCE | SYST_CSR_TICKINT | SYST_CSR_ENABLE;

//init_pins();
__enable_irq();
@@ -317,8 +458,8 @@ void ResetHandler(void)
}
*/
startup_late_hook();
main();
while (1) ;
main();
while (1) ;
}

// TODO: is this needed for c++ and where does it come from?
@@ -332,7 +473,7 @@ char *__brkval = (char *)&_ebss;

void * _sbrk(int incr)
{
//static char *heap_end = (char *)&_ebss;
//static char *heap_end = (char *)&_ebss;
//char *prev = heap_end;
//heap_end += incr;


+ 1158
- 936
teensy3/mk20dx128.h
File diff suppressed because it is too large
View File


+ 146
- 0
teensy3/mk20dx256.ld View File

@@ -0,0 +1,146 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 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 = 256K
RAM (rwx) : ORIGIN = 0x1FFF8000, LENGTH = 64K
}


/* INCLUDE common.ld */


/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 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.
*/



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 = .;
*(.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);
}





+ 9
- 0
teensy3/pins_arduino.h View File

@@ -47,6 +47,14 @@ 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;

const static uint8_t SS = 10;
const static uint8_t MOSI = 11;
@@ -66,6 +74,7 @@ const static uint8_t SCL = 19;
#define NOT_AN_INTERRUPT -1
#define digitalPinToInterrupt(p) ((p) < NUM_DIGITAL_PINS ? (p) : -1)


struct digital_pin_bitband_and_config_table_struct {
volatile uint32_t *reg;
volatile uint32_t *config;

+ 36
- 8
teensy3/pins_teensy.c View File

@@ -351,6 +351,13 @@ void _init_Teensyduino_internal_(void)
FTM1_C0SC = 0x28;
FTM1_C1SC = 0x28;
FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(DEFAULT_FTM_PRESCALE);
#if defined(__MK20DX256__)
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?
@@ -359,17 +366,30 @@ void _init_Teensyduino_internal_(void)



static uint8_t analog_write_res = 8;

// SOPT4 is SIM select clocks?
// FTM is clocked by the bus clock, either 24 or 48 MHz
// input capture can be FTM1_CH0, CMP0 or CMP1 or USB start of frame
// 24 MHz with reload 49152 to match Arduino's speed = 488.28125 Hz

static uint8_t analog_write_res = 8;

void analogWrite(uint8_t pin, int val)
{
uint32_t cval, max;

#if defined(__MK20DX256__)
if (pin == A14) {
uint8_t res = analog_write_res;
if (res < 12) {
val <<= 12 - res;
} else if (res > 12) {
val >>= res - 12;
}
analogWriteDAC0(val);
return;
}
#endif

max = 1 << analog_write_res;
if (val <= 0) {
digitalWrite(pin, LOW);
@@ -390,14 +410,12 @@ void analogWrite(uint8_t pin, int val)
//serial_print("\n");
if (pin == 3 || pin == 4) {
cval = ((uint32_t)val * (uint32_t)(FTM1_MOD + 1)) >> analog_write_res;
//serial_print("FTM1_MOD = ");
//serial_phex32(FTM1_MOD);
//serial_print("\n");
#if defined(__MK20DX256__)
} else if (pin == 25 || pin == 32) {
cval = ((uint32_t)val * (uint32_t)(FTM2_MOD + 1)) >> analog_write_res;
#endif
} else {
cval = ((uint32_t)val * (uint32_t)(FTM0_MOD + 1)) >> analog_write_res;
//serial_print("FTM0_MOD = ");
//serial_phex32(FTM0_MOD);
//serial_print("\n");
}
//serial_print("cval = ");
//serial_phex32(cval);
@@ -443,6 +461,16 @@ void analogWrite(uint8_t pin, int val)
FTM0_C1V = cval;
CORE_PIN23_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
#if defined(__MK20DX256__)
case 32: // PTB18, FTM2_CH0
FTM2_C0V = cval;
CORE_PIN32_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
case 25: // PTB19, FTM1_CH1
FTM2_C1V = cval;
CORE_PIN25_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
#endif
default:
digitalWrite(pin, (val > 127) ? HIGH : LOW);
pinMode(pin, OUTPUT);

Loading…
Cancel
Save