#include <avr/io.h>
Go to the source code of this file.
Data Structures | |
struct | hl_time_s |
store current time More... | |
Defines | |
#define | F_RTC_OSC (32768) |
nominal frequency of low-frequency oscillator | |
Typedefs | |
typedef struct hl_time_s | hl_time_t |
store current time | |
Functions | |
void | hl_rtc_init_osc (void) |
activate low-frequency oscillator | |
void | hl_rtc_init (void) |
initialize low-frequency timer | |
void | hl_sleep_for_tick (uint16_t ms) |
enter power-save mode until next timer overflow or other wake-up event | |
hl_time_t | hl_get_current_time (void) |
return current time | |
uint16_t | hl_get_timer_ticks (void) |
return current tick value | |
void | hl_wakeup_memory (void) |
allow access to external SRAM |
void hl_rtc_init | ( | void | ) |
initialize low-frequency timer
hl_rtc_init() blocks as long as timer1 indicates that the necessary time for oscillator start-up has not elapsed.
{ /* await Overflow Compare on Timer1 - one second has elapsed */ while ((TIFR1 & _BV(OCF1A)) == 0); /* stop timer1 */ TCCR1B = 0; /* reset OCF1A */ TIFR1 = _BV(OCF1A); /* power down timer1 */ power_timer1_disable (); /* wait until previous TCCR2x updates finish */ while (ASSR & (_BV(TCN2UB)|_BV(OCR2AUB)|_BV(TCR2AUB)|_BV(TCR2BUB))); /* set counter register to known state */ TCNT2 = 0; OCR2A = RTC_SCALE-1; TCCR2A = 0 /* | _BV(COM2A1) | _BV(COM2A0) */ /* disconnect OC2A */ /* | _BV(COM2B1) | _BV(COM2B0) */ /* disconnect OC2B */ | _BV(WGM21) /* | _BV(WGM20) */ /* CTC mode */ ; TCCR2B = 0 /* | _BV(FOC2A) | _BV(FOC2B) */ /* no Force Output Compare */ /* | _BV(WGM22) */ /* CTC mode */ | RTC_PRESCALER_CONTROL ; TIFR2 = _BV(OCF2A); /* clear OV interrupt flag */ TIMSK2 = 0 /* | _BV(OCIE2B) */ | _BV(OCIE2A) /* | _BV(TOIE2) */ ; }
void hl_rtc_init_osc | ( | void | ) |
activate low-frequency oscillator
After calling this function, wait at least one second before starting to use the timer, as this is the time the oscillator needs to stabilize.
hl_rtc_init_osc() also starts timer1 to measure the elapsed time since startup of the oscillator. The idea is to be able to do some other initialization tasks which do not need the asynchronous oscillator.
{ power_timer2_enable (); /* disable interrupts from timer during start-up */ TIMSK2 = 0; /* stop timer before enabling asynchronous operation */ TCCR2B &= ~(_BV(CS22)|_BV(CS21)|_BV(CS20)); while (ASSR & _BV(TCR2BUB)); /* enable asynchronous operation with quartz oscillator */ ASSR = _BV(AS2); /* wait until previous TCNT update finishes */ while (ASSR & _BV(TCN2UB)); /* reset counter */ TCNT2 = 0; /* initialize Timer1 */ power_timer1_enable (); /* reset counter */ TCNT1 = 0; /* OC1A/B/C disconnected; WGM: normal mode */ TCCR1A = 0; #define TIM1_PRESCALE (256) /* set compare value (round up to be on safe side) */ OCR1A = F_CPU/TIM1_PRESCALE+1; /* do not generate interrupt */ TIMSK1 = 0; /* reset interrupt flag */ TIFR1 = _BV(OCF1A); /* input capture off; WGM: normal mode; prescaler 1:256 */ TCCR1B = _BV(CS12); /* this starts the timer */ }
void hl_wakeup_memory | ( | void | ) | [inline] |
allow access to external SRAM
hl_wakeup_memory() needs to be called in an interrupt handler when the corresponding interrupt might have woken up the CPU from sleep and the handler is going to acces external memory. Otherwise, the acces will be routed to the USB FIFO chip.
{
XMCRB &= ~_BV(XMM1); /* assume XMM2:0 = 010 */
}