px-fwlib 0.10.0
Cross-platform embedded library and documentation for 8/16/32-bit microcontrollers generated with Doxygen 1.9.2
px_sysclk.c
1/* =============================================================================
2 ____ ___ ____ ___ _ _ ___ __ __ ___ __ __ TM
3 | _ \ |_ _| / ___| / _ \ | \ | | / _ \ | \/ | |_ _| \ \/ /
4 | |_) | | | | | | | | | | \| | | | | | | |\/| | | | \ /
5 | __/ | | | |___ | |_| | | |\ | | |_| | | | | | | | / \
6 |_| |___| \____| \___/ |_| \_| \___/ |_| |_| |___| /_/\_\
7
8 Copyright (c) 2006 Pieter Conradie <https://piconomix.com>
9
10 License: MIT
11 https://github.com/piconomix/px-fwlib/blob/master/LICENSE.md
12
13 Title: px_sysclk.h : System Clock using a TMRx peripheral
14 Author(s): Pieter Conradie
15 Creation Date: 2007-03-31
16
17============================================================================= */
18
19/* _____STANDARD INCLUDES____________________________________________________ */
20#include <avr/io.h>
21#include <avr/interrupt.h>
22
23/* _____PROJECT INCLUDES_____________________________________________________ */
24#include "px_sysclk.h"
25#include "px_board.h"
26
27/* _____LOCAL DEFINITIONS____________________________________________________ */
28#if (PX_SYSCLK_CFG_USE_TMRX == 0)
29
30#define TMR_VECT TIMER0_COMPA_vect
31#define TMR_INT_ENABLE() PX_BIT_SET_HI(TIMSK0, OCIE0A)
32#define TMR_INT_DISABLE() PX_BIT_SET_LO(TIMSK0, OCIE0A)
33#define TMR_INT_IS_ENABLED() PX_BIT_IS_HI(TIMSK0, OCIE0A)
34
35#if (PX_SYSCLK_CFG_TMR_PRESCALER == 1)
36#define PX_SYSCLK_CS 1
37#elif (PX_SYSCLK_CFG_TMR_PRESCALER == 8)
38#define PX_SYSCLK_CS 2
39#elif (PX_SYSCLK_CFG_TMR_PRESCALER == 64)
40#define PX_SYSCLK_CS 3
41#elif (PX_SYSCLK_CFG_TMR_PRESCALER == 256)
42#define PX_SYSCLK_CS 4
43#elif (PX_SYSCLK_CFG_TMR_PRESCALER == 1024)
44#define PX_SYSCLK_CS 5
45#else
46#error "PX_SYSCLK_TMR_PRESCALER value is invalid"
47#endif
48
49#elif (PX_SYSCLK_CFG_USE_TMRX == 1)
50
51#define TMR_VECT TIMER1_COMPA_vect
52#define TMR_INT_ENABLE() PX_BIT_SET_HI(TIMSK1, OCIE1A)
53#define TMR_INT_DISABLE() PX_BIT_SET_LO(TIMSK1, OCIE1A)
54#define TMR_INT_IS_ENABLED() PX_BIT_IS_HI(TIMSK1, OCIE1A)
55#if (PX_SYSCLK_CFG_TMR_PRESCALER == 1)
56#define PX_SYSCLK_CS 1
57#elif (PX_SYSCLK_CFG_TMR_PRESCALER == 8)
58#define PX_SYSCLK_CS 2
59#elif (PX_SYSCLK_CFG_TMR_PRESCALER == 64)
60#define PX_SYSCLK_CS 3
61#elif (PX_SYSCLK_CFG_TMR_PRESCALER == 256)
62#define PX_SYSCLK_CS 4
63#elif (PX_SYSCLK_CFG_TMR_PRESCALER == 1024)
64#define PX_SYSCLK_CS 5
65#else
66#error "PX_SYSCLK_TMR_PRESCALER value is invalid"
67#endif
68
69#elif (PX_SYSCLK_CFG_USE_TMRX == 2)
70
71#define TMR_VECT TIMER2_COMPA_vect
72#define TMR_INT_ENABLE() PX_BIT_SET_HI(TIMSK2, OCIE2A)
73#define TMR_INT_DISABLE() PX_BIT_SET_LO(TIMSK2, OCIE2A)
74#define TMR_INT_IS_ENABLED() PX_BIT_IS_HI(TIMSK2, OCIE2A)
75#if (PX_SYSCLK_CFG_TMR_PRESCALER == 1)
76#define PX_SYSCLK_CS 1
77#elif (PX_SYSCLK_CFG_TMR_PRESCALER == 8)
78#define PX_SYSCLK_CS 2
79#elif (PX_SYSCLK_CFG_TMR_PRESCALER == 32)
80#define PX_SYSCLK_CS 3
81#elif (PX_SYSCLK_CFG_TMR_PRESCALER == 64)
82#define PX_SYSCLK_CS 4
83#elif (PX_SYSCLK_CFG_TMR_PRESCALER == 128)
84#define PX_SYSCLK_CS 5
85#elif (PX_SYSCLK_CFG_TMR_PRESCALER == 256)
86#define PX_SYSCLK_CS 6
87#elif (PX_SYSCLK_CFG_TMR_PRESCALER == 1024)
88#define PX_SYSCLK_CS 7
89#else
90#error "PX_SYSCLK_TMR_PRESCALER value is invalid"
91#endif
92
93#else
94#error "Specified TMR not supported!"
95#endif
96
97
98/* _____MACROS_______________________________________________________________ */
99
100/* _____GLOBAL VARIABLES_____________________________________________________ */
101
102/* _____LOCAL VARIABLES______________________________________________________ */
103static volatile px_sysclk_ticks_t px_sysclk_tick_counter;
104
105#ifdef PX_SYSCLK_CFG_TIMEOUT_PERIOD_TICKS
106static volatile px_sysclk_ticks_t px_sysclk_timeout_counter;
107#endif
108
109/* _____LOCAL FUNCTION DECLARATIONS__________________________________________ */
110
111/* _____LOCAL FUNCTIONS______________________________________________________ */
112/// Timer interrupt handler.
113ISR(TMR_VECT)
114{
115 // Increment counter
116 px_sysclk_tick_counter++;
117
118#ifdef PX_SYSCLK_CFG_TIMEOUT_PERIOD_TICKS
119 // Decrement timeout counter
120 if(--px_sysclk_timeout_counter == 0)
121 {
122 // Reset timeout counter
123 px_sysclk_timeout_counter = PX_SYSCLK_CFG_TIMEOUT_PERIOD_TICKS;
124#endif
125
126#ifdef PX_SYSCLK_CFG_ON_PERIODIC_TIMEOUT
127 // Call periodic timeout function
128 PX_SYSCLK_CFG_ON_PERIODIC_TIMEOUT();
129#endif
130
131#ifdef PX_SYSCLK_CFG_TIMEOUT_PERIOD_TICKS
132 }
133#endif
134}
135
136/* _____GLOBAL FUNCTIONS_____________________________________________________ */
138{
139#if (PX_SYSCLK_CFG_USE_TMRX == 0)
140
141 // Initialise timer interrupt @ CLK/PX_SYSCLK_TMR_PRESCALER in CTC mode ("Clear Timer on Compare")
142 TCCR0A = (1 << WGM01) | (0 << WGM00);
143 TCCR0B = (0 << WGM02) | (PX_SYSCLK_CS << CS00);
144 // Reset TMR counter
145 TCNT0 = 0;
146 // Calculate and set maximum TMR counter value. When TCNT reaches this
147 // value, an interrupt is generated and TCNT is reset to 0.
149
150#elif (PX_SYSCLK_CFG_USE_TMRX == 1)
151
152 // Initialise timer interrupt @ CLK/PX_SYSCLK_TMR_PRESCALER in CTC mode ("Clear Timer on Compare")
153 TCCR1A = (0 << WGM11) | (0 << WGM10);
154 TCCR1B = (0 << WGM13) | (1 << WGM12) | (PX_SYSCLK_CS << CS10);
155 // Reset TMR counter
156 TCNT1 = 0;
157 // Calculate and set maximum TMR counter value. When TCNT reaches this
158 // value, an interrupt is generated and TCNT is reset to 0.
160
161#elif (PX_SYSCLK_CFG_USE_TMRX == 2)
162
163 // Initialise timer interrupt @ CLK/PX_SYSCLK_TMR_PRESCALER in CTC mode ("Clear Timer on Compare")
164 TCCR2A = (1 << WGM21) | (0 << WGM20);
165 TCCR2B = (0 << WGM22) | (PX_SYSCLK_CS << CS20);
166 // Reset TMR counter
167 TCNT2 = 0;
168 // Calculate and set maximum TMR counter value. When TCNT reaches this
169 // value, an interrupt is generated and TCNT is reset to 0.
171
172#else
173 #error "Specified TMR not supported!"
174#endif
175
176#ifdef PX_SYSCLK_CFG_TIMEOUT_PERIOD_TICKS
177 // Reset timeout counter
178 px_sysclk_timeout_counter = PX_SYSCLK_CFG_TIMEOUT_PERIOD_TICKS;
179#endif
180
181 // Enable timer interrupt
182 TMR_INT_ENABLE();
183}
184
186{
187 bool enabled = TMR_INT_IS_ENABLED();
188
189 TMR_INT_DISABLE();
190
191 return enabled;
192}
193
195{
196 TMR_INT_ENABLE();
197}
198
200{
201 px_sysclk_ticks_t counter;
202
203 // Disable timer interrupt to perform atomic access
204 TMR_INT_DISABLE();
205 // Fetch current time
206 counter = px_sysclk_tick_counter;
207 // Enable timer interrupt
208 TMR_INT_ENABLE();
209
210 return counter;
211}
bool px_sysclk_disable(void)
Disable system clock.
Definition: px_sysclk.c:185
#define PX_SYSCLK_CFG_TIMEOUT_PERIOD_TICKS
Specify periodic timeout (in sysclk ticks)
#define PX_SYSCLK_CFG_TMR_PRESCALER
Specify TMR Prescaler.
#define PX_SYSCLK_CFG_TICKS_PER_SEC
The number of system clock ticks per second.
void px_sysclk_enable(void)
Enable system clock.
Definition: px_sysclk.c:194
#define F_CPU
Processor frequency in Hz.
Definition: px_board.h:52
#define PX_UDIV_ROUND(dividend, divisor)
Calculate unsigned division with rounding to nearest integer value.
Definition: px_defs.h:284
px_sysclk_ticks_t px_sysclk_get_tick_count(void)
Return number of ticks since system clock started.
Definition: px_sysclk.c:97
uint32_t px_sysclk_ticks_t
Size definition of the tick counter.
Definition: px_sysclk.h:74
void px_sysclk_init(void)
Start system clock (one clock tick every 1/PX_SYSCLK_TICKS_PER_SEC seconds)
Definition: px_sysclk.c:79