@@ -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); } |
@@ -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; |
@@ -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 | |||
}; | |||
@@ -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 |
@@ -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 | |||
@@ -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(); |
@@ -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 | |||
@@ -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) : | |||
); |
@@ -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); |
@@ -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(); |
@@ -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); | |||
} | |||
@@ -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)); |
@@ -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 { |
@@ -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 |
@@ -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 | |||
@@ -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; |
@@ -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); |
@@ -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); |
@@ -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 | |||
} | |||
@@ -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; |