//----------------------------------------------------------------------------- static void initSDHC() { #ifdef HAS_KINETIS_MPU // Allow SDHC Bus Master access. MPU_RGDAAC0 |= 0x0C000000; #endif // Enable SDHC clock. SIM_SCGC3 |= SIM_SCGC3_SDHC; // Disable GPIO clock. enableGPIO(false); // Reset SDHC. Use default Water Mark Level of 16. SDHC_SYSCTL = SDHC_SYSCTL_RSTA; while (SDHC_SYSCTL & SDHC_SYSCTL_RSTA) { } // Set initial SCK rate. setSdclk(400); enableGPIO(true); // Enable desired IRQSTAT bits. SDHC_IRQSTATEN = SDHC_IRQSTATEN_MASK; NVIC_SET_PRIORITY(IRQ_SDHC, 6*16); NVIC_ENABLE_IRQ(IRQ_SDHC); // Send 80 clocks to card. SDHC_SYSCTL |= SDHC_SYSCTL_INITA; while (SDHC_SYSCTL & SDHC_SYSCTL_INITA) { } }
bool PulsePositionInput::begin(uint8_t pin) { uint32_t channel; volatile void *reg; if (FTM0_MOD != 0xFFFF || FTM0_SC != (FTM_SC_CLKS(1) | FTM_SC_PS(0))) { FTM0_SC = 0; FTM0_CNT = 0; FTM0_MOD = 0xFFFF; FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0); FTM0_MODE = 0; } switch (pin) { case 5: channel = 7; reg = &FTM0_C7SC; break; case 6: channel = 4; reg = &FTM0_C4SC; break; case 9: channel = 2; reg = &FTM0_C2SC; break; case 10: channel = 3; reg = &FTM0_C3SC; break; case 20: channel = 5; reg = &FTM0_C5SC; break; case 21: channel = 6; reg = &FTM0_C6SC; break; case 22: channel = 0; reg = &FTM0_C0SC; break; case 23: channel = 1; reg = &FTM0_C1SC; break; default: return false; } prev = 0; write_index = 255; available_flag = false; ftm = (struct ftm_channel_struct *)reg; ftm->csc = cscEdge; // input capture & interrupt on rising edge list[channel] = this; channelmask |= (1<<channel); *portConfigRegister(pin) = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; NVIC_SET_PRIORITY(IRQ_FTM0, 32); NVIC_ENABLE_IRQ(IRQ_FTM0); return true; }
/** * SnoozeClass Constructor */ SnoozeClass::SnoozeClass( void ) { SIM_SOPT1CFG |= SIM_SOPT1CFG_USSWE_MASK; SIM_SOPT1 &= ~SIM_SOPT1_USBSSTBY_MASK; attachInterruptVector( IRQ_LLWU, wakeupISR ); NVIC_SET_PRIORITY( IRQ_LLWU, 32 ); clock_mode = mcg_mode( ); }
static void update_dma(void) { if (xmit_buffer_tail == xmit_buffer_head) return; DBG_DMA_CHANNEL->CCR = (DMA_Priority_Low | DMA_PeripheralDataSize_Byte | DMA_MemoryDataSize_Byte | DMA_PeripheralInc_Disable | DMA_MemoryInc_Enable | DMA_Mode_Normal | DMA_DIR_PeripheralDST | DMA_CCR4_TCIE ); DBG_DMA_CHANNEL->CPAR = (u32)&DBG_UART->DR; DBG_DMA_CHANNEL->CMAR = (u32)xmit_buffer_head; if (xmit_buffer_head < xmit_buffer_tail) { DBG_DMA_CHANNEL->CNDTR = xmit_buffer_tail - xmit_buffer_head; dma_end = xmit_buffer_tail; } else { DBG_DMA_CHANNEL->CNDTR = XMIT_BUFFER_END - xmit_buffer_head; dma_end = xmit_buffer; } NVIC_ENABLE_INT(DMA1_Channel4_IRQChannel); NVIC_SET_PRIORITY(DMA1_Channel4_IRQChannel, 2); DBG_DMA_CHANNEL->CCR |=DMA_CCR4_EN; }
void configure_nvic(void) { // Start in the idle state, but first wake up to check for keep steppers enabled option. NVIC_ENABLE_IRQ(IRQ_PIT_CH0); NVIC_ENABLE_IRQ(IRQ_PIT_CH1); NVIC_ENABLE_IRQ(IRQ_PIT_CH2); // This is already done in the default boot sequence, but that could change and enabling is idempotent... // port b is responsible for limits and the sync protocol - rather critical to have interrupts. NVIC_ENABLE_IRQ(IRQ_PORTB); NVIC_ENABLE_IRQ(IRQ_I2C0); // Limits/sync and pin toggle/reset isr get the highest priority NVIC_SET_PRIORITY(IRQ_PORTB, 0); NVIC_SET_PRIORITY(IRQ_PIT_CH1, 0); // Followed by the main stepper isr NVIC_SET_PRIORITY(IRQ_PIT_CH0, 1<<4); // Lastly, the sync reset/timeout isr and i2c communication NVIC_SET_PRIORITY(IRQ_I2C0, 2<<4); NVIC_SET_PRIORITY(IRQ_PIT_CH2, 2<<4); // All other ISRs are also priority zero, but shouldn't really ever fire }
// ------------------------------------------------------------ // configuters a PIT's registers, function pointer, and enables // interrupts, effectively starting the timer upon completion // ------------------------------------------------------------ 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; // point to the correct PIT ISR PIT_ISR[PIT_id] = myISR; // write value to register and enable interrupt *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 }
bool PulsePositionOutput::begin(uint8_t txPin, uint8_t framePin) { uint32_t channel; volatile void *reg; if (FTM0_MOD != 0xFFFF || (FTM0_SC & 0x7F) != FTM0_SC_VALUE) { FTM0_SC = 0; FTM0_CNT = 0; FTM0_MOD = 0xFFFF; FTM0_SC = FTM0_SC_VALUE; #if defined(KINETISK) FTM0_MODE = 0; #endif } switch (txPin) { case 6: channel = 4; reg = &FTM0_C4SC; break; case 9: channel = 2; reg = &FTM0_C2SC; break; case 10: channel = 3; reg = &FTM0_C3SC; break; case 20: channel = 5; reg = &FTM0_C5SC; break; case 22: channel = 0; reg = &FTM0_C0SC; break; case 23: channel = 1; reg = &FTM0_C1SC; break; #if defined(KINETISK) case 5: channel = 7; reg = &FTM0_C7SC; break; case 21: channel = 6; reg = &FTM0_C6SC; break; #endif default: return false; } if (framePin < NUM_DIGITAL_PINS) { framePinReg = portOutputRegister(framePin); framePinMask = digitalPinToBitMask(framePin); pinMode(framePin, OUTPUT); FRAME_PIN_SET(); } else { framePinReg = NULL; } state = 0; current_channel = 0; total_channels = 0; ftm = (struct ftm_channel_struct *)reg; ftm->cv = 200; CSC_CHANGE(ftm, cscSet); // set on compare match & interrupt list[channel] = this; channelmask |= (1<<channel); *portConfigRegister(txPin) = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; NVIC_SET_PRIORITY(IRQ_FTM0, 32); NVIC_ENABLE_IRQ(IRQ_FTM0); return true; }
bool FreqMeasureMulti::begin(uint32_t pin) { switch (pin) { case 22: channel = 0; CORE_PIN22_CONFIG = PORT_PCR_MUX(4); break; case 23: channel = 1; CORE_PIN23_CONFIG = PORT_PCR_MUX(4); break; case 9: channel = 2; CORE_PIN9_CONFIG = PORT_PCR_MUX(4); break; case 10: channel = 3; CORE_PIN10_CONFIG = PORT_PCR_MUX(4); break; case 6: channel = 4; CORE_PIN6_CONFIG = PORT_PCR_MUX(4); break; case 20: channel = 5; CORE_PIN20_CONFIG = PORT_PCR_MUX(4); break; #if defined(KINETISK) case 21: channel = 6; CORE_PIN21_CONFIG = PORT_PCR_MUX(4); break; case 5: channel = 7; CORE_PIN5_CONFIG = PORT_PCR_MUX(4); break; #endif default: channel = 8; return false; } if (FTM0_MOD != 0xFFFF || (FTM0_SC & 0x7F) != FTM_SC_VALUE) { FTM0_SC = 0; FTM0_CNT = 0; FTM0_MOD = 0xFFFF; FTM0_SC = FTM_SC_VALUE; #ifdef KINETISK FTM0_MODE = 0; #endif } capture_msw = 0; capture_previous = 0; buffer_head = 0; buffer_tail = 0; volatile uint32_t *csc = &FTM0_C0SC + channel * 2; #if defined(KINETISL) *csc = 0; delayMicroseconds(1); #endif *csc = 0b01000100; list[channel] = this; channelmask |= (1 << channel); NVIC_SET_PRIORITY(IRQ_FTM0, 48); NVIC_ENABLE_IRQ(IRQ_FTM0); return true; }
bool PulsePositionOutput::begin(uint8_t txPin, uint8_t framePin) { uint32_t channel; volatile void *reg; if (FTM0_MOD != 0xFFFF || FTM0_SC != (FTM_SC_CLKS(1) | FTM_SC_PS(0))) { FTM0_SC = 0; FTM0_CNT = 0; FTM0_MOD = 0xFFFF; FTM0_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0); FTM0_MODE = 0; } switch (txPin) { case 5: channel = 7; reg = &FTM0_C7SC; break; case 6: channel = 4; reg = &FTM0_C4SC; break; case 9: channel = 2; reg = &FTM0_C2SC; break; case 10: channel = 3; reg = &FTM0_C3SC; break; case 20: channel = 5; reg = &FTM0_C5SC; break; case 21: channel = 6; reg = &FTM0_C6SC; break; case 22: channel = 0; reg = &FTM0_C0SC; break; case 23: channel = 1; reg = &FTM0_C1SC; break; default: return false; } if (framePin < NUM_DIGITAL_PINS) { framePinReg = portOutputRegister(framePin); pinMode(framePin, OUTPUT); *framePinReg = 1; } else { framePinReg = NULL; } state = 0; current_channel = 0; total_channels = 0; ftm = (struct ftm_channel_struct *)reg; ftm->cv = 200; ftm->csc = cscSet; // set on compare match & interrupt list[channel] = this; channelmask |= (1<<channel); *portConfigRegister(txPin) = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE; NVIC_SET_PRIORITY(IRQ_FTM0, 32); NVIC_ENABLE_IRQ(IRQ_FTM0); return true; }
bool PulsePositionInput::begin(uint8_t pin) { uint32_t channel; volatile void *reg; if (FTM0_MOD != 0xFFFF || (FTM0_SC & 0x7F) != FTM0_SC_VALUE) { FTM0_SC = 0; FTM0_CNT = 0; FTM0_MOD = 0xFFFF; FTM0_SC = FTM0_SC_VALUE; #if defined(KINETISK) FTM0_MODE = 0; #endif } switch (pin) { case 6: channel = 4; reg = &FTM0_C4SC; break; case 9: channel = 2; reg = &FTM0_C2SC; break; case 10: channel = 3; reg = &FTM0_C3SC; break; case 20: channel = 5; reg = &FTM0_C5SC; break; case 22: channel = 0; reg = &FTM0_C0SC; break; case 23: channel = 1; reg = &FTM0_C1SC; break; #if defined(KINETISK) case 21: channel = 6; reg = &FTM0_C6SC; break; case 5: channel = 7; reg = &FTM0_C7SC; break; #endif default: return false; } prev = 0; write_index = 255; available_flag = false; ftm = (struct ftm_channel_struct *)reg; list[channel] = this; channelmask |= (1<<channel); *portConfigRegister(pin) = PORT_PCR_MUX(4); CSC_CHANGE(ftm, cscEdge); // input capture & interrupt on rising edge NVIC_SET_PRIORITY(IRQ_FTM0, 32); NVIC_ENABLE_IRQ(IRQ_FTM0); return true; }
void FlexCAN::begin (uint32_t baud, const CAN_filter_t &mask, uint8_t txAlt, uint8_t rxAlt) { // set up the pins if (flexcanBase == FLEXCAN0_BASE) { dbg_println ("Begin setup of CAN0"); #if defined(__MK66FX1M0__) || defined(__MK64FX512__) // 3=PTA12=CAN0_TX, 4=PTA13=CAN0_RX (default) // 29=PTB18=CAN0_TX, 30=PTB19=CAN0_RX (alternative) if (txAlt == 1) CORE_PIN29_CONFIG = PORT_PCR_MUX(2); else CORE_PIN3_CONFIG = PORT_PCR_MUX(2); // | PORT_PCR_PE | PORT_PCR_PS; if (rxAlt == 1) CORE_PIN30_CONFIG = PORT_PCR_MUX(2); else CORE_PIN4_CONFIG = PORT_PCR_MUX(2); #else // 3=PTA12=CAN0_TX, 4=PTA13=CAN0_RX (default) // 32=PTB18=CAN0_TX, 25=PTB19=CAN0_RX (alternative) if (txAlt == 1) CORE_PIN32_CONFIG = PORT_PCR_MUX(2); else CORE_PIN3_CONFIG = PORT_PCR_MUX(2); // | PORT_PCR_PE | PORT_PCR_PS; if (rxAlt == 1) CORE_PIN25_CONFIG = PORT_PCR_MUX(2); else CORE_PIN4_CONFIG = PORT_PCR_MUX(2); #endif } #if defined(INCLUDE_FLEXCAN_CAN1) else if (flexcanBase == FLEXCAN1_BASE) { dbg_println("Begin setup of CAN1"); // 33=PTE24=CAN1_TX, 34=PTE25=CAN1_RX (default) // NOTE: Alternative CAN1 pins are not broken out on Teensy 3.6 CORE_PIN33_CONFIG = PORT_PCR_MUX(2); CORE_PIN34_CONFIG = PORT_PCR_MUX(2);// | PORT_PCR_PE | PORT_PCR_PS; } #endif // select clock source 16MHz xtal OSC0_CR |= OSC_ERCLKEN; if (flexcanBase == FLEXCAN0_BASE) { SIM_SCGC6 |= SIM_SCGC6_FLEXCAN0; #if defined(INCLUDE_FLEXCAN_CAN1) } else if (flexcanBase == FLEXCAN1_BASE) { SIM_SCGC3 |= SIM_SCGC3_FLEXCAN1; #endif } FLEXCANb_CTRL1(flexcanBase) &= ~FLEXCAN_CTRL_CLK_SRC; // enable CAN FLEXCANb_MCR (flexcanBase) |= FLEXCAN_MCR_FRZ; FLEXCANb_MCR (flexcanBase) &= ~FLEXCAN_MCR_MDIS; while (FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_LPM_ACK) ; // soft reset FLEXCANb_MCR (flexcanBase) ^= FLEXCAN_MCR_SOFT_RST; while (FLEXCANb_MCR (flexcanBase) & FLEXCAN_MCR_SOFT_RST) ; // wait for freeze ack while (!(FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_FRZ_ACK)) ; // disable self-reception FLEXCANb_MCR (flexcanBase) |= FLEXCAN_MCR_SRX_DIS; /* now using a system that tries to automatically generate a viable baud setting. Bear these things in mind: - The master clock is 16Mhz - You can freely divide it by anything from 1 to 256 - There is always a start bit (+1) - The rest (prop, seg1, seg2) are specified 1 less than their actual value (aka +1) - This gives the low end bit timing as 5 (1 + 1 + 2 + 1) and the high end 25 (1 + 8 + 8 + 8) A worked example: 16Mhz clock, divisor = 19+1, bit values add up to 16 = 16Mhz / 20 / 16 = 50k baud */ // have to find a divisor that ends up as close to the target baud as possible while keeping the end result between 5 and 25 uint32_t divisor = 0; uint32_t bestDivisor = 0; uint32_t result = 16000000 / baud / (divisor + 1); int error = baud - (16000000 / (result * (divisor + 1))); int bestError = error; while (result > 5) { divisor++; result = 16000000 / baud / (divisor + 1); if (result <= 25) { error = baud - (16000000 / (result * (divisor + 1))); if (error < 0) error *= -1; // if this error is better than we've ever seen then use it - it's the best option if (error < bestError) { bestError = error; bestDivisor = divisor; } // If this is equal to a previously good option then // switch to it but only if the bit time result was in the middle of the range // this biases the output to use the middle of the range all things being equal // Otherwise it might try to use a higher divisor and smaller values for prop, seg1, seg2 // and that's not necessarily the best idea. if ((error == bestError) && (result > 11) && (result < 19)) { bestError = error; bestDivisor = divisor; } } } divisor = bestDivisor; result = 16000000 / baud / (divisor + 1); if ((result < 5) || (result > 25) || (bestError > 300)) { Serial.println ("Abort in CAN begin. Couldn't find a suitable baud config!"); return; } result -= 5; // the bitTimingTable is offset by 5 since there was no reason to store bit timings for invalid numbers uint8_t propSeg = bitTimingTable[result][0]; uint8_t pSeg1 = bitTimingTable[result][1]; uint8_t pSeg2 = bitTimingTable[result][2]; // baud rate debug information dbg_println ("Bit time values:"); dbg_print ("Prop = "); dbg_println (propSeg + 1); dbg_print ("Seg1 = "); dbg_println (pSeg1 + 1); dbg_print ("Seg2 = "); dbg_println (pSeg2 + 1); dbg_print ("Divisor = "); dbg_println (divisor + 1); FLEXCANb_CTRL1 (flexcanBase) = (FLEXCAN_CTRL_PROPSEG(propSeg) | FLEXCAN_CTRL_RJW(1) | FLEXCAN_CTRL_ERR_MSK | FLEXCAN_CTRL_PSEG1(pSeg1) | FLEXCAN_CTRL_PSEG2(pSeg2) | FLEXCAN_CTRL_PRESDIV(divisor)); // enable per-mailbox filtering FLEXCANb_MCR(flexcanBase) |= FLEXCAN_MCR_IRMQ; // now have to set mask and filter for all the Rx mailboxes or they won't receive anything by default. for (uint8_t c = 0; c < NUM_MAILBOXES - numTxMailboxes; c++) { setMask (0, c); setFilter (mask, c); } // start the CAN FLEXCANb_MCR(flexcanBase) &= ~(FLEXCAN_MCR_HALT); // wait till exit of freeze mode while (FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_FRZ_ACK) ; // wait till ready while (FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_NOT_RDY) ; setNumTxBoxes (2); #if defined(__MK20DX256__) NVIC_SET_PRIORITY (IRQ_CAN_MESSAGE, IRQ_PRIORITY); NVIC_ENABLE_IRQ (IRQ_CAN_MESSAGE); #elif defined(__MK64FX512__) NVIC_SET_PRIORITY (IRQ_CAN0_MESSAGE, IRQ_PRIORITY); NVIC_ENABLE_IRQ (IRQ_CAN0_MESSAGE); #elif defined(__MK66FX1M0__) if (flexcanBase == FLEXCAN0_BASE) { NVIC_SET_PRIORITY (IRQ_CAN0_MESSAGE, IRQ_PRIORITY); NVIC_ENABLE_IRQ (IRQ_CAN0_MESSAGE); } else { NVIC_SET_PRIORITY (IRQ_CAN1_MESSAGE, IRQ_PRIORITY); NVIC_ENABLE_IRQ (IRQ_CAN1_MESSAGE); } #endif // enable interrupt masks for all 16 mailboxes FLEXCANb_IMASK1 (flexcanBase) = 0xFFFF; dbg_println ("CAN initialized properly"); }
/******************************************************************************* * Enable digital interrupt and configure the pin *******************************************************************************/ void SnoozeDigital::enableDriver( void ) { if ( mode == RUN_LP ) { return; } #if defined(KINETISK) uint64_t _pin = pin; isr_pin = pin; if ( mode == VLPW || mode == VLPS ) { return_isr_a_enabled = NVIC_IS_ENABLED( IRQ_PORTA ); return_isr_b_enabled = NVIC_IS_ENABLED( IRQ_PORTB ); return_isr_c_enabled = NVIC_IS_ENABLED( IRQ_PORTC ); return_isr_d_enabled = NVIC_IS_ENABLED( IRQ_PORTD ); return_isr_e_enabled = NVIC_IS_ENABLED( IRQ_PORTE ); NVIC_DISABLE_IRQ(IRQ_PORTA); NVIC_DISABLE_IRQ(IRQ_PORTB); NVIC_DISABLE_IRQ(IRQ_PORTC); NVIC_DISABLE_IRQ(IRQ_PORTD); NVIC_DISABLE_IRQ(IRQ_PORTE); NVIC_CLEAR_PENDING(IRQ_PORTA); NVIC_CLEAR_PENDING(IRQ_PORTB); NVIC_CLEAR_PENDING(IRQ_PORTC); NVIC_CLEAR_PENDING(IRQ_PORTD); NVIC_CLEAR_PENDING(IRQ_PORTE); int priority = nvic_execution_priority( );// get current priority // if running from interrupt set priority higher than current interrupt priority = ( priority < 256 ) && ( ( priority - 16 ) > 0 ) ? priority - 16 : 128; return_priority_a = NVIC_GET_PRIORITY( IRQ_PORTA );//get current priority return_priority_b = NVIC_GET_PRIORITY( IRQ_PORTB );//get current priority return_priority_c = NVIC_GET_PRIORITY( IRQ_PORTC );//get current priority return_priority_d = NVIC_GET_PRIORITY( IRQ_PORTD );//get current priority return_priority_e = NVIC_GET_PRIORITY( IRQ_PORTE );//get current priority NVIC_SET_PRIORITY( IRQ_PORTA, priority );//set priority to new level NVIC_SET_PRIORITY( IRQ_PORTB, priority );//set priority to new level NVIC_SET_PRIORITY( IRQ_PORTC, priority );//set priority to new level NVIC_SET_PRIORITY( IRQ_PORTD, priority );//set priority to new level NVIC_SET_PRIORITY( IRQ_PORTE, priority );//set priority to new level __disable_irq( ); return_porta_irq = _VectorsRam[IRQ_PORTA+16];// save prev isr handler return_portb_irq = _VectorsRam[IRQ_PORTB+16];// save prev isr handler return_portc_irq = _VectorsRam[IRQ_PORTC+16];// save prev isr handler return_portd_irq = _VectorsRam[IRQ_PORTD+16];// save prev isr handler return_porte_irq = _VectorsRam[IRQ_PORTE+16];// save prev isr handler attachInterruptVector( IRQ_PORTA, isr );// set snooze digA isr attachInterruptVector( IRQ_PORTB, isr );// set snooze digB isr attachInterruptVector( IRQ_PORTC, isr );// set snooze digC isr attachInterruptVector( IRQ_PORTD, isr );// set snooze digD isr attachInterruptVector( IRQ_PORTE, isr );// set snooze digE isr __enable_irq( ); 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 ); } _pin = pin; while ( __builtin_popcountll( _pin ) ) { uint32_t pinNumber = 63 - __builtin_clzll( _pin );// get pin if ( pinNumber > 33 ) break; uint32_t pin_mode = irqType[pinNumber] >> 4;// get type uint32_t pin_type = irqType[pinNumber] & 0x0F;// get mode volatile uint32_t *config; config = portConfigRegister( pinNumber ); return_core_pin_config[pinNumber] = *config; if ( pin_mode == INPUT || pin_mode == INPUT_PULLUP ) {// setup pin mode/type/interrupt *portModeRegister( pinNumber ) = 0; if ( pin_mode == INPUT ) *config = PORT_PCR_MUX( 1 ); else *config = PORT_PCR_MUX( 1 ) | PORT_PCR_PE | PORT_PCR_PS;// pullup if ( mode == VLPW || mode == VLPS ) { attachDigitalInterrupt( pinNumber, pin_type );// set pin interrupt } else { llwu_configure_pin_mask( pinNumber, mode ); } } else { //pinMode( pinNumber, pin_mode ); //digitalWriteFast( pinNumber, pin_type ); } _pin &= ~( ( uint64_t )1 << pinNumber );// remove pin from list } #elif defined(KINETISL) uint32_t _pin = pin; isr_pin = pin; if ( mode == VLPW || mode == VLPS ) {// if using sleep must setup pin interrupt to wake return_isr_a_enabled = NVIC_IS_ENABLED( IRQ_PORTA ); return_isr_cd_enabled = NVIC_IS_ENABLED( IRQ_PORTCD ); NVIC_DISABLE_IRQ(IRQ_PORTA); NVIC_DISABLE_IRQ(IRQ_PORTCD); NVIC_CLEAR_PENDING(IRQ_PORTA); NVIC_CLEAR_PENDING(IRQ_PORTCD); int priority = nvic_execution_priority( );// get current priority // if running from interrupt set priority higher than current interrupt priority = ( priority < 256 ) && ( ( priority - 16 ) > 0 ) ? priority - 16 : 128; return_priority_a = NVIC_GET_PRIORITY( IRQ_PORTA );//get current priority return_priority_cd = NVIC_GET_PRIORITY( IRQ_PORTCD );//get current priority NVIC_SET_PRIORITY( IRQ_PORTA, priority );//set priority to new level NVIC_SET_PRIORITY( IRQ_PORTCD, priority );//set priority to new level __disable_irq( ); return_porta_irq = _VectorsRam[IRQ_PORTA+16];// save prev isr handler return_portcd_irq = _VectorsRam[IRQ_PORTCD+16];// save prev isr handler attachInterruptVector( IRQ_PORTA, isr );// set snooze isr attachInterruptVector( IRQ_PORTCD, isr );// set snooze isr __enable_irq( ); NVIC_ENABLE_IRQ( IRQ_PORTA ); NVIC_ENABLE_IRQ( IRQ_PORTCD ); } _pin = pin; while ( __builtin_popcount( _pin ) ) { uint32_t pinNumber = 31 - __builtin_clz( _pin );// get pin if ( pinNumber > 33 ) break; uint32_t pin_mode = irqType[pinNumber] >> 4;// get type uint32_t pin_type = irqType[pinNumber] & 0x0F;// get mode volatile uint32_t *config; config = portConfigRegister( pinNumber ); return_core_pin_config[pinNumber] = *config; if ( pin_mode == INPUT || pin_mode == INPUT_PULLUP ) {// setup pin mode/type/interrupt *portModeRegister( pinNumber ) &= ~digitalPinToBitMask( pinNumber ); // TODO: atomic if ( pin_mode == INPUT ) *config = PORT_PCR_MUX( 1 ); else *config = PORT_PCR_MUX( 1 ) | PORT_PCR_PE | PORT_PCR_PS;// pullup if ( pin_mode == VLPW || pin_mode == VLPS ) { attachDigitalInterrupt( pinNumber, pin_type );// set pin interrupt } else { llwu_configure_pin_mask( pinNumber, pin_mode ); } } else { //pinMode( pinNumber, pin_mode ); //digitalWriteFast( pinNumber, pin_type ); } _pin &= ~( ( uint32_t )1 << pinNumber );// remove pin from list } #endif }
/******************************************************************************* * Disable interrupt and configure pin to orignal state. *******************************************************************************/ void SnoozeDigital::disableDriver( void ) { if ( mode == RUN_LP ) { return; } #if defined(KINETISK) uint64_t _pin = pin; while ( __builtin_popcountll( _pin ) ) { uint32_t pinNumber = 63 - __builtin_clzll( _pin ); if ( pinNumber > 33 ) break; *portModeRegister( pinNumber ) = 0; volatile uint32_t *config; config = portConfigRegister( pinNumber ); *config = return_core_pin_config[pinNumber]; _pin &= ~( ( uint64_t )1 << pinNumber );// remove pin from list } #elif defined(KINETISL) uint32_t _pin = pin; while ( __builtin_popcount( _pin ) ) { uint32_t pinNumber = 31 - __builtin_clz( _pin ); if ( pinNumber > 33 ) break; *portModeRegister( pinNumber ) &= ~digitalPinToBitMask( pinNumber ); volatile uint32_t *config; config = portConfigRegister( pinNumber ); *config = return_core_pin_config[pinNumber]; _pin &= ~( ( uint32_t )1 << pinNumber );// remove pin from list } #endif if ( mode == VLPW || mode == VLPS ) { #if defined(KINETISK) NVIC_SET_PRIORITY( IRQ_PORTA, return_priority_a );//set priority to new level NVIC_SET_PRIORITY( IRQ_PORTB, return_priority_b );//set priority to new level NVIC_SET_PRIORITY( IRQ_PORTC, return_priority_c );//set priority to new level NVIC_SET_PRIORITY( IRQ_PORTD, return_priority_d );//set priority to new level NVIC_SET_PRIORITY( IRQ_PORTE, return_priority_e );//set priority to new level __disable_irq( ); attachInterruptVector( IRQ_PORTA, return_porta_irq );// set snooze isr attachInterruptVector( IRQ_PORTB, return_portb_irq );// set snooze isr attachInterruptVector( IRQ_PORTC, return_portc_irq );// set snooze isr attachInterruptVector( IRQ_PORTD, return_portd_irq );// set snooze isr attachInterruptVector( IRQ_PORTE, return_porte_irq );// set snooze isr __enable_irq( ); if ( return_isr_a_enabled == 0 ) NVIC_DISABLE_IRQ( IRQ_PORTA ); if ( return_isr_b_enabled == 0 ) NVIC_DISABLE_IRQ( IRQ_PORTB ); if ( return_isr_c_enabled == 0 ) NVIC_DISABLE_IRQ( IRQ_PORTC ); if ( return_isr_d_enabled == 0 ) NVIC_DISABLE_IRQ( IRQ_PORTD ); if ( return_isr_e_enabled == 0 ) NVIC_DISABLE_IRQ( IRQ_PORTE ); #elif defined(KINETISL) NVIC_SET_PRIORITY( IRQ_PORTA, return_priority_a );//set priority to new level NVIC_SET_PRIORITY( IRQ_PORTCD, return_priority_cd );//set priority to new level __disable_irq( ); attachInterruptVector( IRQ_PORTA, return_porta_irq );// set snooze isr attachInterruptVector( IRQ_PORTCD, return_portcd_irq );// set snooze isr __enable_irq( ); if ( return_isr_a_enabled == 0 ) NVIC_DISABLE_IRQ( IRQ_PORTA ); if ( return_isr_cd_enabled == 0 ) NVIC_DISABLE_IRQ( IRQ_PORTCD ); #endif } }
/******************************************************************************* * Enable Driver *******************************************************************************/ void SnoozeCompare::enableDriver( void ) { if ( mode == RUN_LP ) { return; } if ( mode == VLPW || mode == VLPS ) { IRQ_NUMBER_t IRQ_CMP; switch (pin) { case 11: IRQ_CMP = IRQ_CMP0; break; #if defined(KINETISK) case 9: IRQ_CMP = IRQ_CMP1; break; case 4: IRQ_CMP = IRQ_CMP2; break; #endif default: IRQ_CMP = IRQ_CMP; return; } return_priority = NVIC_GET_PRIORITY( IRQ_CMP );//get current priority int priority = nvic_execution_priority( );// get current priority // if running from handler mode set priority higher than current handler priority = ( priority < 256 ) && ( ( priority - 16 ) > 0 ) ? priority - 16 : 128; NVIC_SET_PRIORITY( IRQ_CMP, priority );//set priority to new level __disable_irq( ); return_cmp_irq = _VectorsRam[IRQ_CMP+16];// save prev isr attachInterruptVector( IRQ_CMP, wakeupIsr ); __enable_irq( ); } if ( SIM_SCGC4 & SIM_SCGC4_CMP ) SIM_SCGC4_clock_active = true; else SIM_SCGC4 |= SIM_SCGC4_CMP; CR0 = *cmpx_cr0; CR1 = *cmpx_cr1; SCR = *cmpx_scr; FPR = *cmpx_fpr; MUXCR = *cmpx_muxcr; DACCR = *cmpx_daccr; uint8_t _pin = 0; *cmpx_cr0 = 0; *cmpx_cr1 = 0; *cmpx_scr = 0; #if defined(__MKL26Z64__) || defined(__MK66FX1M0__) if ( SIM_SCGC5 & SIM_SCGC5_LPTIMER ) SIM_SCGC5_clock_active = true; else SIM_SCGC5 |= SIM_SCGC5_LPTIMER; PSR = LPTMR0_PSR; CMR = LPTMR0_CMR; CSR = LPTMR0_CSR; #endif if ( pin == 11 ) { if ( mode >= LLS ) llwu_configure_modules_mask( LLWU_CMP0_MOD ); return_core_pin_config[0] = CORE_PIN11_CONFIG; CORE_PIN11_CONFIG = PORT_PCR_MUX( 0 ); _pin = 0x00; } else if ( pin == 4 ) { #if defined(KINETISK) if ( mode >= LLS ) llwu_configure_modules_mask( LLWU_CMP2_MOD ); return_core_pin_config[1] = CORE_PIN4_CONFIG; CORE_PIN4_CONFIG = PORT_PCR_MUX( 0 ); _pin = 0x01; #else return; #endif } else if ( pin == 9 ) { #if defined(KINETISK) if ( mode >= LLS ) llwu_configure_modules_mask( LLWU_CMP1_MOD ); return_core_pin_config[2] = CORE_PIN9_CONFIG; CORE_PIN9_CONFIG = PORT_PCR_MUX( 0 ); _pin = 0x01; #else return; #endif } // save if isr is already enabled and enable isr if not if ( mode == VLPW || mode == VLPS ) { IRQ_NUMBER_t IRQ_CMP; switch (pin) { case 11: IRQ_CMP = IRQ_CMP0; break; #if defined(KINETISK) case 9: IRQ_CMP = IRQ_CMP1; break; case 4: IRQ_CMP = IRQ_CMP2; break; #endif default: IRQ_CMP = IRQ_CMP; return; } return_isr_enabled = NVIC_IS_ENABLED( IRQ_CMP ); if ( return_isr_enabled == 0 ) NVIC_ENABLE_IRQ( IRQ_CMP ); } // setup compare *cmpx_cr0 = CMP_CR0_FILTER_CNT( 0x07 ); if ( type == CHANGE ) *cmpx_scr = CMP_SCR_CFF | CMP_SCR_CFR | CMP_SCR_IEF | CMP_SCR_IER; else if ( type == RISING || type == HIGH ) *cmpx_scr = CMP_SCR_CFF | CMP_SCR_CFR | CMP_SCR_IER; else if ( type == FALLING || type == LOW ) *cmpx_scr = CMP_SCR_CFF | CMP_SCR_CFR | CMP_SCR_IEF; else return; uint8_t tap = ( threshold_crossing/0.0515625 ) - 1; *cmpx_fpr = 0x00; *cmpx_muxcr = CMP_MUXCR_MSEL( 0x07 ) | CMP_MUXCR_PSEL( _pin ); *cmpx_daccr = CMP_DACCR_DACEN | CMP_DACCR_VRSEL | CMP_DACCR_VOSEL( tap ); #if defined(__MKL26Z64__) || defined(__MK66FX1M0__) // compare needs lptmr to operate in low power with LC, 3.6 *cmpx_cr1 = CMP_CR1_EN | CMP_CR1_TRIGM; SIM_SCGC5 |= SIM_SCGC5_LPTIMER; LPTMR0_CSR = 0; LPTMR0_PSR = LPTMR_PSR_PBYP | LPTMR_PSR_PCS( LPTMR_LPO );//LPO Clock LPTMR0_CMR = 1; LPTMR0_CSR = LPTMR_CSR_TEN | LPTMR_CSR_TCF; #else *cmpx_cr1 = CMP_CR1_EN; #endif }
void i2c_setup() { for ( uint8_t ch = ISSI_I2C_FirstBus_define; ch < ISSI_I2C_Buses_define + ISSI_I2C_FirstBus_define; ch++ ) { #if defined(_kinetis_) volatile uint8_t *I2C_F = (uint8_t*)(&I2C0_F) + i2c_offset[ch]; volatile uint8_t *I2C_FLT = (uint8_t*)(&I2C0_FLT) + i2c_offset[ch]; volatile uint8_t *I2C_C1 = (uint8_t*)(&I2C0_C1) + i2c_offset[ch]; volatile uint8_t *I2C_C2 = (uint8_t*)(&I2C0_C2) + i2c_offset[ch]; switch ( ch ) { case 0: // Enable I2C internal clock SIM_SCGC4 |= SIM_SCGC4_I2C0; // Bus 0 // External pull-up resistor PORTB_PCR0 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); PORTB_PCR1 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); break; #if defined(_kii_v2_) case 1: // Enable I2C internal clock SIM_SCGC4 |= SIM_SCGC4_I2C1; // Bus 1 // External pull-up resistor PORTC_PCR10 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); PORTC_PCR11 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); break; #endif } // SCL Frequency Divider #if ISSI_Chip_31FL3731_define == 1 && defined(_kii_v1_) // 0x53 -> 48 MHz / (2 * 72) = 333.333 kBaud // 0x40 => mul(2) // 0x13 => ICR(30) *I2C_F = 0x53; *I2C_FLT = 0x05; #elif ISSI_Chip_31FL3731_define == 1 && defined(_kii_v2_) // 0x4E -> 36 MHz / (2 * 56) = 321.428 kBaud // 0x40 => mul(2) // 0x0E => ICR(56) *I2C_F = 0x4E; *I2C_FLT = 0x04; #elif ISSI_Chip_31FL3732_define == 1 || ISSI_Chip_31FL3733_define == 1 || ISSI_Chip_31FL3736_define == 1 /* // Works // 0x84 -> 36 MHz / (4 * 28) = 321.428 kBaud // 0x80 => mul(4) // 0x04 => ICR(28) *I2C_F = 0x84; *I2C_FLT = 0x02; // Also works, 80 fps, no errors (flicker?) // 0x0C -> 36 MHz / (1 * 44) = 818.181 kBaud // 0x00 => mul(1) // 0x0C => ICR(44) *I2C_F = 0x0C; *I2C_FLT = 0x02; // Glitch protection, reduce if you see bus errors */ // Also works, 86 fps, no errors, using frame delay of 50 us // 0x40 -> 36 MHz / (2 * 20) = 900 kBaud // 0x40 => mul(2) // 0x00 => ICR(20) *I2C_F = 0x40; *I2C_FLT = 0x02; #endif *I2C_C1 = I2C_C1_IICEN; *I2C_C2 = I2C_C2_HDRS; // High drive select switch ( ch ) { case 0: // Enable I2C Interrupt NVIC_ENABLE_IRQ( IRQ_I2C0 ); // Set priority below USB, but not too low to maintain performance NVIC_SET_PRIORITY( IRQ_PIT_CH0, I2C_Priority_define ); break; #if defined(_kii_v2_) case 1: // Enable I2C Interrupt NVIC_ENABLE_IRQ( IRQ_I2C1 ); // Set priority below USB, but not too low to maintain performance NVIC_SET_PRIORITY( IRQ_PIT_CH1, I2C_Priority_define ); break; #endif } #elif defined(_sam_) #if ISSI_Chip_31FL3731_define == 1 #define BAUD 400000 #define CK 1 #elif ISSI_Chip_31FL3732_define == 1 || ISSI_Chip_31FL3733_define == 1 || ISSI_Chip_31FL3736_define == 1 #define BAUD 800000 #define CK 0 #endif switch ( ch ) { case 0: // Enable Peripheral / Disable PIO PIOA->PIO_PDR = (1 << 3) | (1 << 4); // Enable i2c clock PMC->PMC_PCER0 = (1 << ID_TWI0); break; case 1: MATRIX->CCFG_SYSIO |= CCFG_SYSIO_SYSIO4 | CCFG_SYSIO_SYSIO5; // Switch PB4 from TDI to GPIO PIOB->PIO_PDR = (1 << 4) | (1 << 5); PMC->PMC_PCER0 = (1 << ID_TWI1); break; } Twi *twi_dev = twi_devs[ch]; uint16_t div = (F_CPU/BAUD - 4) / (2<<CK); // Set clock twi_dev->TWI_CWGR = TWI_CWGR_CLDIV(div) + TWI_CWGR_CHDIV(div) + TWI_CWGR_CKDIV(CK); // Enable master mode twi_dev->TWI_CR = TWI_CR_MSDIS | TWI_CR_SVDIS; twi_dev->TWI_CR = TWI_CR_MSEN; switch ( ch ) { case 0: NVIC_SetPriority(TWI0_IRQn, I2C_Priority_define); NVIC_EnableIRQ(TWI0_IRQn); break; case 1: NVIC_SetPriority(TWI1_IRQn, I2C_Priority_define); NVIC_EnableIRQ(TWI1_IRQn); break; } #endif } }
/******************************************************************************* * Disable Driver *******************************************************************************/ void SnoozeCompare::disableDriver( void ) { if ( mode == RUN_LP ) { return; } if ( mode == VLPW || mode == VLPS ) { IRQ_NUMBER_t IRQ_CMP; switch (pin) { case 11: IRQ_CMP = IRQ_CMP0; break; #if defined(KINETISK) case 9: IRQ_CMP = IRQ_CMP1; break; case 4: IRQ_CMP = IRQ_CMP2; break; #endif default: IRQ_CMP = IRQ_CMP; return; } if ( return_isr_enabled == 0 ) NVIC_DISABLE_IRQ( IRQ_CMP ); NVIC_SET_PRIORITY( IRQ_CMP, return_priority ); __disable_irq( ); attachInterruptVector( IRQ_CMP, return_cmp_irq );// return prev interrupt __enable_irq( ); } if ( pin == 11 ) { CORE_PIN11_CONFIG = return_core_pin_config[0]; } else if ( pin == 4 ) { #if defined(KINETISK) CORE_PIN4_CONFIG = return_core_pin_config[1]; #else return; #endif } else if ( pin == 9 ) { #if defined(KINETISK) CORE_PIN9_CONFIG = return_core_pin_config[2]; #else return; #endif } #if defined(__MKL26Z64__) || defined(__MK66FX1M0__) LPTMR0_PSR = PSR; LPTMR0_CMR = CMR; LPTMR0_CSR = CSR; if ( !SIM_SCGC5_clock_active ) SIM_SCGC5 &= ~SIM_SCGC5_LPTIMER; #endif *cmpx_cr0 = CR0; *cmpx_cr1 = CR1; *cmpx_scr = SCR; *cmpx_fpr = FPR; *cmpx_muxcr = MUXCR; *cmpx_daccr = DACCR; if ( !SIM_SCGC4_clock_active ) SIM_SCGC4 &= ~SIM_SCGC4_CMP; }
//upgrade original audiointerrupt if needed (hackish...) void init_interrupt() { if (NVIC_GET_PRIORITY(IRQ_AUDIO) == 240) { NVIC_SET_PRIORITY(IRQ_AUDIO, 224); } }