Exemplo n.º 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);
}
Exemplo n.º 2
0
/***************************************************************************//**
 * @brief
 *    Deinitialize RTCDRV driver.
 *
 * @details
 *    Will disable interrupts and turn off the clock to the underlying hardware
 *    timer.
 *    If integration with SLEEP module is enabled it will remove any
 *    restriction that are set on energy mode usage.
 *
 * @return
 *    @ref ECODE_EMDRV_RTCDRV_OK.
 ******************************************************************************/
Ecode_t RTCDRV_DeInit( void )
{
  // Disable and clear all interrupt sources.
  NVIC_DISABLEIRQ();
  RTC_INTDISABLE( RTC_ALL_INTS );
  RTC_INTCLEAR( RTC_ALL_INTS );
  NVIC_CLEARPENDINGIRQ();

  // Disable RTC module and its clock.
#if defined( RTCDRV_USE_RTC )
  RTC_Enable( false );
  CMU_ClockEnable( cmuClock_RTC, false );
#elif defined( RTCDRV_USE_RTCC )
  RTCC_Enable( false );
  CMU_ClockEnable( cmuClock_RTCC, false );
#endif

#if defined( EMODE_NEVER_ALLOW_EM3EM4 )
  // End EM3 and EM4 blocking.
  SLEEP_SleepBlockEnd( sleepEM3 );
#endif

#if defined( EMODE_DYNAMIC )
  // End EM3 and EM4 blocking if a block start has been set.
  if ( sleepBlocked ) {
    SLEEP_SleepBlockEnd( sleepEM3 );
  }
#endif

  // Mark the driver as uninitialized.
  rtcdrvIsInitialized = false;

  return ECODE_EMDRV_RTCDRV_OK;
}
/**************************************************************************//**
 * @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);
}
Exemplo n.º 4
0
void RTCC_init(void)
{
	RTCC_SOSCenable();
	RTCC_Enable();
	RTCC_SetWriteDisable();
	RTCC_AlarmDisable();
	RTCC_OutputDisable();
	IntClearFlag(INT_REAL_TIME_CLOCK);
}
Exemplo n.º 5
0
void RTCC_SetAlarmEnable(int enable)
{
	while (RTCALRM & 0x1000);	// wait ALRMSYNC to be off
	RTCC_Disable();
	if (enable)
		RTCALRMbits.ALRMEN = 1;   	// Alarm is enabled
	else
		RTCALRMbits.ALRMEN = 0;   	// Alarm is disabled
	RTCC_Enable();
}
Exemplo n.º 6
0
rtccRes RTCC_Open(unsigned long tm, unsigned long dt, int drift)
{
	RTCC_SOSCenable();
	RTCC_SetTime(tm);
	RTCC_SetDate(dt);
	RTCC_SetCalibration(drift);
	RTCC_Enable();
	RTCC_AlarmDisable();
	RTCC_OutputDisable();
	RTCC_SetWriteDisable();
	IntClearFlag(INT_REAL_TIME_CLOCK);
}
Exemplo n.º 7
0
void RTCC_SetAlarmInitialPulse(int enable)
{
	while (RTCALRM & 0x1000);	// wait ALRMSYNC to be off
	RTCC_Disable();				// 
	RTCC_SetAlarmEnable(False);// Alarm is disabled, PIV is writable
	if (enable)
		RTCALRMbits.PIV = 1;		// the initial value of the Alarm Pulse is high
	else
		RTCALRMbits.PIV = 0;		// the initial value of the Alarm Pulse is low
	RTCC_SetAlarmEnable(True);	// Alarm is enabled
	RTCC_Enable();					// 
}
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 vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCountAfterSleep;
eSleepModeStatus eSleepAction;
TickType_t xModifiableIdleTime;

	/* THIS FUNCTION IS CALLED WITH THE SCHEDULER SUSPENDED. */

	/* Make sure the RTC reload value does not overflow the counter. */
	if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
	{
		xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
	}

	/* Calculate the reload value required to wait xExpectedIdleTime tick
	periods. */
	ulReloadValue = ulReloadValueForOneTick * xExpectedIdleTime;
	if( ulReloadValue > ulStoppedTimerCompensation )
	{
		/* Compensate for the fact that the RTC is going to be stopped
		momentarily. */
		ulReloadValue -= ulStoppedTimerCompensation;
	}

	/* Stop the RTC momentarily.  The time the RTC is stopped for is accounted
	for as best it can be, but using the tickless mode will inevitably result
	in some tiny drift of the time maintained by the kernel with respect to
	calendar time. */
	RTCC_Enable( false );

	/* Enter a critical section but don't use the taskENTER_CRITICAL() method as
	that will mask interrupts that should exit sleep mode. */
	INT_Disable();
	__asm volatile( "dsb" );
	__asm volatile( "isb" );

	/* The tick flag is set to false before sleeping.  If it is true when sleep
	mode is exited then sleep mode was probably exited because the tick was
	suppressed for the entire xExpectedIdleTime period. */
	ulTickFlag = pdFALSE;

	/* If a context switch is pending then abandon the low power entry as the
	context switch might have been pended by an external interrupt that	requires
	processing. */
	eSleepAction = eTaskConfirmSleepModeStatus();
	if( eSleepAction == eAbortSleep )
	{
		/* Restart tick and continue counting to complete the current time
		slice. */
		RTCC_Enable( true );

		/* Re-enable interrupts - see comments above the RTCC_Enable() call
		above. */
		INT_Enable();
	}
	else
	{
		RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ulReloadValue );

		/* Restart the RTC. */
		RTCC_Enable( true );

		/* Allow the application to define some pre-sleep processing. */
		xModifiableIdleTime = xExpectedIdleTime;
		configPRE_SLEEP_PROCESSING( xModifiableIdleTime );

		/* xExpectedIdleTime being set to 0 by configPRE_SLEEP_PROCESSING()
		means the application defined code has already executed the WAIT
		instruction. */
		if( xModifiableIdleTime > 0 )
		{
			__asm volatile( "dsb" );
			SLEEP_Sleep();
			__asm volatile( "isb" );
		}

		/* Allow the application to define some post sleep processing. */
		configPOST_SLEEP_PROCESSING( xModifiableIdleTime );

		/* Stop RTC.  Again, the time the SysTick is stopped for is accounted
		for as best it can be, but using the tickless mode will	inevitably
		result in some tiny drift of the time maintained by the	kernel with
		respect to calendar time. */
		RTCC_Enable( false );
		ulCountAfterSleep = RTCC_CounterGet();

		/* Re-enable interrupts - see comments above the INT_Enable() call
		above. */
		INT_Enable();
		__asm volatile( "dsb" );
		__asm volatile( "isb" );

		if( ulTickFlag != pdFALSE )
		{
			/* The tick interrupt has already executed, although because this
			function is called with the scheduler suspended the actual tick
			processing will not occur until after this function has exited.
			The tick interrupt handler will already have pended the tick
			processing in the kernel.  As the pending tick will be processed as
			soon as this function exits, the tick value	maintained by the tick
			is stepped forward by one less than the	time spent sleeping.  The
			actual stepping of the tick appears later in this function. */
			ulCompleteTickPeriods = xExpectedIdleTime - 1UL;

			/* The interrupt should have reset the CCV value. */
			configASSERT( RTCC_ChannelCCVGet( lpRTCC_CHANNEL ) == ulReloadValueForOneTick );
		}
		else
		{
			/* Something other than the tick interrupt ended the sleep.  How
			many complete tick periods passed while the processor was
			sleeping? */
			ulCompleteTickPeriods = ulCountAfterSleep / ulReloadValueForOneTick;

			/* The next interrupt is configured to occur at whatever fraction of
			the current tick period remains by setting the reload value back to
			that required for one tick, and truncating the count to remove the
			counts that are greater than the reload value. */
			RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ulReloadValueForOneTick );
			ulCountAfterSleep %= ulReloadValueForOneTick;
			RTCC_CounterSet( ulCountAfterSleep );
		}

		/* Restart the RTC so it runs up to the alarm value.  The alarm value
		will get set to the value required to generate exactly one tick period
		the next time the RTC interrupt executes. */
		RTCC_Enable( true );

		/* Wind the tick forward by the number of tick periods that the CPU
		remained in a low power state. */
		vTaskStepTick( ulCompleteTickPeriods );
	}