//-----------------------------------------------------------------------------
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) {
  }
}
Exemple #2
0
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;
}
Exemple #3
0
/**
 *  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( );
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #9
0
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
    }
}
Exemple #14
0
/*******************************************************************************
 *  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
}
Exemple #15
0
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
	}
}
Exemple #16
0
/*******************************************************************************
 *  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);
	}
}