Пример #1
0
int rtc_init(volatile avr32_rtc_t *rtc, unsigned char osc_type, unsigned char psel)
{
  // If exit, it means that the configuration has not been set correctly
  if (osc_type > (1 << AVR32_RTC_CTRL_CLK32_SIZE) - 1 ||
      psel > (1 << AVR32_RTC_CTRL_PSEL_SIZE) - 1)
    return 0;

  // If we use the 32-kHz oscillator, we have to enable it first
  if (osc_type == RTC_OSC_32KHZ)
  {
    // Select the 32-kHz oscillator crystal
    pm_enable_osc32_crystal(&AVR32_PM);
    // Enable the 32-kHz clock and wait until the osc32 clock is ready.
    pm_enable_clk32(&AVR32_PM, AVR32_PM_OSCCTRL32_STARTUP_0_RCOSC);
  }

  // Wait until the rtc accepts writes to the CTRL register
  while (rtc_is_busy(rtc));

  // Set the new RTC configuration
  rtc->ctrl = osc_type << AVR32_RTC_CTRL_CLK32_OFFSET |
              psel << AVR32_RTC_CTRL_PSEL_OFFSET |
              AVR32_RTC_CTRL_CLKEN_MASK;

  // Wait until write is done
  while (rtc_is_busy(rtc));

  // Set the counter value to 0
  rtc_set_value(rtc, 0x00000000);
  // Set the top value to 0xFFFFFFFF
  rtc_set_top_value(rtc, 0xFFFFFFFF);

  return 1;
}
Пример #2
0
void rtc_set_value(volatile avr32_rtc_t *rtc, unsigned long val)
{
  // Wait until we can write into the VAL register
  while (rtc_is_busy(rtc));
  // Set the new val value
  rtc->val = val;
  // Wait until write is done
  while (rtc_is_busy(rtc));
}
Пример #3
0
void rtc_disable(volatile avr32_rtc_t *rtc)
{
  // Wait until the rtc CTRL register is up-to-date
  while (rtc_is_busy(rtc));
  // Disable the RTC
  rtc->ctrl &= ~AVR32_RTC_CTRL_EN_MASK;
  // Wait until write is done
  while (rtc_is_busy(rtc));
}
Пример #4
0
void rtc_enable_wake_up(volatile avr32_rtc_t *rtc)
{
  // Wait until the rtc CTRL register is up-to-date
  while (rtc_is_busy(rtc));
  // Enable the wake up of the RTC
  rtc->ctrl |= AVR32_RTC_CTRL_WAKE_EN_MASK;
  // Wait until write is done
  while (rtc_is_busy(rtc));
}
Пример #5
0
/**
 * \brief Set alarm time
 *
 * Will set absolute alarm time that will call the callback specifed by \ref
 * rtc_set_callback on completion. Or possibly use \ref
 * rtc_alarm_has_triggered to check for it.
 *
 * Any pending alarm will be overwritten with this function.
 *
 * \param time Absolute time value. See also \ref rtc_min_alarm_time
 * \pre Needs interrupts disabled if used from several contexts
 */
void rtc_set_alarm(uint32_t time)
{
	RTC.INTCTRL = RTC_OVERFLOW_INT_LEVEL;
	while (rtc_is_busy());
	RTC.COMP = time;
	rtc_data.alarm_low = time;
	rtc_data.alarm_high = time >> 16;
	while (rtc_is_busy());
	RTC.INTCTRL = RTC_COMPARE_INT_LEVEL
		| RTC_OVERFLOW_INT_LEVEL;
}
Пример #6
0
static int
omaprtc_settime(todr_chip_handle_t tch, struct clock_ymdhms *dt)
{
	struct omaprtc_softc *sc = tch->cookie;
	int s;

	s = disable_interrupts(I32_bit);

	while (rtc_is_busy()) {
		;
	}

	/* It's ok to write these without stopping the
	 * RTC, because the BUSY mechanism lets us guarantee
	 * that we're not in the middle of, e.g., rolling
	 * seconds into minutes.
	 */

	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
			  YEARS_REG, TOBCD(dt->dt_year - BASEYEAR));
	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
			  MONTHS_REG, TOBCD(dt->dt_mon));
	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
			  WEEKS_REG, TOBCD(dt->dt_wday & 0x0f));
	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
			  DAYS_REG, TOBCD(dt->dt_day));
	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
			  SECONDS_REG, TOBCD(dt->dt_sec));
	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
			  HOURS_REG, TOBCD(dt->dt_hour));
	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
			  MINUTES_REG, TOBCD(dt->dt_min));
	restore_interrupts(s);
        return 0;
}
Пример #7
0
/**
 * \brief Set current time
 *
 * \param time Time value to set
 */
void rtc_set_time(uint32_t time)
{
	RTC.CTRL = RTC_PRESCALER_OFF_gc;
	while (rtc_is_busy());
	RTC.CNT = time;
	rtc_data.counter_high = time >> 16;
	RTC.CTRL = CONFIG_RTC_PRESCALER;
}
Пример #8
0
static int
omaprtc_gettime(todr_chip_handle_t tch, struct clock_ymdhms *dt)
{
	struct omaprtc_softc *sc = tch->cookie;
	int s;

	/* Wait for RTC_STATUS_REG:BUSY to go low to
	 * guarantee our read is correct.  BUSY will
	 * only be high for one 32kHz period (30.5us)
	 * each second, so we'll usually pass right
	 * through.
	 *
	 * Watch RTC_CTRL_REG:STOP_RTC as well so
	 * we don't spin forever if someone disables the RTC.
	 *
	 * Turn interrupts off, because we are only allowed
	 * to read/write the registers for 1/2 of a 32kHz
	 * clock period (= 15us) after detecting that BUSY
	 * is low.
	 */

	s = disable_interrupts(I32_bit);

	while (rtc_is_busy()) {
		;
	}

	dt->dt_year =
		FROMBCD(bus_space_read_1(sc->sc_iot,
					 sc->sc_ioh,
					 YEARS_REG)) + BASEYEAR;
	dt->dt_mon =
		FROMBCD(bus_space_read_1(sc->sc_iot,
					 sc->sc_ioh,
					 MONTHS_REG));
	dt->dt_wday =
		FROMBCD(bus_space_read_1(sc->sc_iot,
					 sc->sc_ioh,
					 WEEKS_REG) & 0x0f);
	dt->dt_day =
		FROMBCD(bus_space_read_1(sc->sc_iot,
					 sc->sc_ioh,
					 DAYS_REG));
	dt->dt_sec =
		FROMBCD(bus_space_read_1(sc->sc_iot,
					 sc->sc_ioh,
					 SECONDS_REG));
	dt->dt_hour =
		FROMBCD(bus_space_read_1(sc->sc_iot,
					 sc->sc_ioh,
					 HOURS_REG));
	dt->dt_min =
		FROMBCD(bus_space_read_1(sc->sc_iot,
					 sc->sc_ioh,
					 MINUTES_REG));
	restore_interrupts(s);
        return 0;
}
Пример #9
0
/**
 * \brief Set current time
 *
 * \param time Time value to set
 */
void rtc_set_time(uint32_t time)
{
	RTC32.CTRL = 0;

	while (rtc_is_busy());

	RTC32.CNT = time;
	RTC32.CTRL = RTC32_ENABLE_bm;
}
Пример #10
0
/**
 * \brief Initialize the 32kHz oscillator and RTC32
 *
 * Starts up the 32kHz oscillator in the backup system and initializes the
 * RTC32.
 *
 * \note When the backup system is used, the function \ref
 * rtc_vbat_system_check should be called to determine if a re-initialization
 * must be done.
 */
void rtc_init(void)
{
	sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_RTC);
	// Set up VBAT system and start oscillator
	vbat_init();

	// Disable the RTC32 module before setting it up
	RTC32.CTRL = 0;

	while (rtc_is_busy());

	// Set up maximum period and start at 0
	RTC32.PER = 0xffffffff;
	RTC32.CNT = 0;

	while (rtc_is_busy());

	RTC32.INTCTRL = 0;
	RTC32.CTRL = RTC32_ENABLE_bm;

	// Make sure it's sync'ed before return
	while (rtc_is_busy());
}
Пример #11
0
/**
 * \brief Get current time
 *
 * \return Current time value
 *
 * \note For devices with the errata "RTC Counter value not correctly read
 *       after sleep", this can return old values shortly after waking up from
 *       sleep.
 * \note Without this errata this function can block for up to 1 RTC
 *       clock source cycle after waking up from sleep.
 */
uint32_t rtc_get_time(void)
{
	irqflags_t flags;
	uint16_t   count_high;
	uint16_t   count_low;

	while (rtc_is_busy());

	flags = cpu_irq_save();
	count_high = rtc_data.counter_high;
	count_low = RTC.CNT;
	// Test for possible pending increase of high count value
	if ((count_low == 0) && (RTC.INTFLAGS & RTC_OVFIF_bm))
		count_high++;
	cpu_irq_restore(flags);

	return ((uint32_t)count_high << 16) | count_low;
}