예제 #1
0
void rtc_init(void)
{
    /* enable clocks */
    CMU_ClockEnable(cmuClock_CORELE, true);
    CMU_ClockEnable(cmuClock_RTCC, true);

    /* reset and initialize peripheral */
    EFM32_CREATE_INIT(init, RTCC_Init_TypeDef, RTCC_INIT_DEFAULT,
        .conf.enable = false,
        .conf.presc = rtccCntPresc_32768,
        .conf.cntMode = rtccCntModeCalendar
    );

    RTCC_Reset();
    RTCC_Init(&init.conf);

    /* initialize alarm channel */
    RTCC_CCChConf_TypeDef init_channel = RTCC_CH_INIT_COMPARE_DEFAULT;

    RTCC_ChannelInit(0, &init_channel);

    /* enable interrupt */
    NVIC_ClearPendingIRQ(RTCC_IRQn);
    NVIC_EnableIRQ(RTCC_IRQn);

    /* enable peripheral */
    RTCC_Enable(true);
}
/**************************************************************************//**
 * @brief Enables LFECLK and selects clock source for RTCC
 *        Sets up the RTCC to generate an interrupt every second.
 *****************************************************************************/
static void rtccSetup(unsigned int frequency)
{
  RTCC_Init_TypeDef rtccInit = RTCC_INIT_DEFAULT;
  rtccInit.presc = rtccCntPresc_1;

  palClockSetup(cmuClock_LFE);
  /* Enable RTCC clock */
  CMU_ClockEnable(cmuClock_RTCC, true);

  /* Initialize RTC */
  rtccInit.enable   = false;  /* Do not start RTC after initialization is complete. */
  rtccInit.debugRun = false;  /* Halt RTC when debugging. */
  rtccInit.cntWrapOnCCV1 = true;   /* Wrap around on CCV1 match. */
  RTCC_Init(&rtccInit);

  /* Interrupt at given frequency. */
  RTCC_CCChConf_TypeDef ccchConf = RTCC_CH_INIT_COMPARE_DEFAULT;
  ccchConf.compMatchOutAction = rtccCompMatchOutActionToggle;
  RTCC_ChannelInit(1, &ccchConf);
  RTCC_ChannelCCVSet(1, (CMU_ClockFreqGet(cmuClock_RTCC) / frequency) - 1);

#ifndef INCLUDE_PAL_GPIO_PIN_AUTO_TOGGLE_HW_ONLY
  /* Enable interrupt */
  NVIC_EnableIRQ(RTCC_IRQn);
  RTCC_IntEnable(RTCC_IEN_CC1);
#endif

  RTCC->CNT = _RTCC_CNT_RESETVALUE;
  /* Start Counter */
  RTCC_Enable(true);
}
void vPortSetupTimerInterrupt( void )
{
	/* Configure the RTCC to generate the RTOS tick interrupt. */

	/* The maximum number of ticks that can be suppressed depends on the clock
	frequency. */
	xMaximumPossibleSuppressedTicks = ULONG_MAX / ulReloadValueForOneTick;

	/* Ensure LE modules are accessible. */
	CMU_ClockEnable( cmuClock_CORELE, true );

	/* Use LFXO. */
	CMU_ClockSelectSet( cmuClock_LFE, cmuSelect_LFXO );

	/* Enable clock to the RTC module. */
	CMU_ClockEnable( cmuClock_RTCC, true );

	/* Use channel 1 to generate the RTOS tick interrupt. */
	RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ulReloadValueForOneTick );

	RTCC_Init( &xRTCInitStruct );
	RTCC_ChannelInit( lpRTCC_CHANNEL, &xRTCCChannel1InitStruct );
	RTCC_EM4WakeupEnable( true );

	/* Disable RTCC interrupt. */
	RTCC_IntDisable( _RTCC_IF_MASK );
	RTCC_IntClear( _RTCC_IF_MASK );
	RTCC->CNT = _RTCC_CNT_RESETVALUE;

	/* The tick interrupt must be set to the lowest priority possible. */
	NVIC_SetPriority( RTCC_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY );
	NVIC_ClearPendingIRQ( RTCC_IRQn );
	NVIC_EnableIRQ( RTCC_IRQn );
	RTCC_IntEnable( RTCC_IEN_CC1 );
	RTCC_Enable( true );

	#if( lpUSE_TEST_TIMER == 1 )
	{
		void prvSetupTestTimer( void );

		/* A second timer is used to test the path where the MCU is brought out
		of a low power state by a timer other than the tick timer. */
		prvSetupTestTimer();
	}
	#endif
}
void lp_ticker_set_interrupt(timestamp_t timestamp)
{
    uint64_t timestamp_ticks;
    uint64_t current_ticks = RTCC_CounterGet();
    timestamp_t current_time = ((uint64_t)(current_ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT));

    /* Initialize RTC */
    lp_ticker_init();

    /* calculate offset value */
    timestamp_t offset = timestamp - current_time;
    if(offset > 0xEFFFFFFF) offset = 100;

    /* map offset to RTC value */
    // ticks = offset * RTC frequency div 1000000
    timestamp_ticks = ((uint64_t)offset * (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) / 1000000;
    // checking the rounding. If timeout is wanted between RTCC ticks, irq should be configured to
    // trigger in the latter RTCC-tick. Otherwise ticker-api fails to send timer event to its client
    if(((timestamp_ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) < offset){
        timestamp_ticks++;
    }

    timestamp_ticks += current_ticks;

    /* RTCC has 32 bit resolution */
    timestamp_ticks &= 0xFFFFFFFF;

    /* check for RTCC limitation */
    if((timestamp_ticks - RTCC_CounterGet()) >= 0x80000000) timestamp_ticks = RTCC_CounterGet() + 2;

    /* init channel */
    RTCC_CCChConf_TypeDef ccchConf = RTCC_CH_INIT_COMPARE_DEFAULT;
    RTCC_ChannelInit(0,&ccchConf);
    /* Set callback */
    RTCC_ChannelCCVSet(0, (uint32_t)timestamp_ticks);
    RTCC_IntEnable(RTCC_IF_CC0);
}
예제 #5
0
/***************************************************************************//**
 * @brief
 *    Initialize RTCDRV driver.
 *
 * @details
 *    Will enable all necessary clocks. Initializes internal datastructures
 *    and configures the underlying hardware timer.
 *
 * @return
 *    @ref ECODE_EMDRV_RTCDRV_OK.
 ******************************************************************************/
Ecode_t RTCDRV_Init( void )
{
  if ( rtcdrvIsInitialized == true ) {
    return ECODE_EMDRV_RTCDRV_OK;
  }
  rtcdrvIsInitialized = true;

  // Ensure LE modules are clocked.
  CMU_ClockEnable( cmuClock_CORELE, true );

#if defined( CMU_LFECLKEN0_RTCC )
  // Enable LFECLK in CMU (will also enable oscillator if not enabled).
  CMU_ClockSelectSet( cmuClock_LFE, RTCDRV_OSC );
#else
  // Enable LFACLK in CMU (will also enable oscillator if not enabled).
  CMU_ClockSelectSet( cmuClock_LFA, RTCDRV_OSC );
#endif

#if defined( RTCDRV_USE_RTC )
  // Set clock divider.
  CMU_ClockDivSet( cmuClock_RTC, RTC_DIVIDER );

  // Enable RTC module clock.
  CMU_ClockEnable( cmuClock_RTC, true );

  // Initialize RTC.
  RTC_Init( &initRTC );

#elif defined( RTCDRV_USE_RTCC )
  // Set clock divider.
  initRTCC.presc = (RTCC_CntPresc_TypeDef)CMU_DivToLog2( RTC_DIVIDER );

  // Enable RTCC module clock.
  CMU_ClockEnable( cmuClock_RTCC, true );

  // Initialize RTCC.
  RTCC_Init( &initRTCC );

  // Set up Compare channel.
  RTCC_ChannelInit( 1, &initRTCCCompareChannel );
#endif

  // Disable RTC/RTCC interrupt generation.
  RTC_INTDISABLE( RTC_ALL_INTS );
  RTC_INTCLEAR( RTC_ALL_INTS );

  RTC_COUNTERRESET();

  // Clear and then enable RTC interrupts in NVIC.
  NVIC_CLEARPENDINGIRQ();
  NVIC_ENABLEIRQ();

#if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
  // Enable overflow interrupt for wallclock.
  RTC_INTENABLE( RTC_OF_INT );
#endif

  // Reset RTCDRV internal data structures/variables.
  memset( timer, 0, sizeof( timer ) );
  inTimerIRQ             = false;
  rtcRunning             = false;
  startTimerNestingLevel = 0;
#if defined( EMODE_DYNAMIC )
  sleepBlocked           = false;
#endif

#if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
  wallClockOverflowCnt = 0;
  wallClockTimeBase    = 0;

#if defined( EMODE_NEVER_ALLOW_EM3EM4 )
  // Always block EM3 and EM4 if wallclock is running.
  SLEEP_SleepBlockBegin( sleepEM3 );
#endif

#endif

  return ECODE_EMDRV_RTCDRV_OK;
}