Hanna
Sourcecode Batteriemanagementsystem
pll.h
gehe zur Dokumentation dieser Datei
1 
43 /*
44  * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45  */
46 #ifndef XMEGA_PLL_H_INCLUDED
47 #define XMEGA_PLL_H_INCLUDED
48 
49 #include <compiler.h>
50 
56 #define NR_PLLS 1
57 #define PLL_MIN_HZ 10000000UL
58 #define PLL_MAX_HZ 200000000UL
59 #define PLL_NR_OPTIONS 0
60 
61 enum pll_source {
63  PLL_SRC_RC2MHZ = OSC_PLLSRC_RC2M_gc,
65  PLL_SRC_RC32MHZ = OSC_PLLSRC_RC32M_gc,
67  PLL_SRC_XOSC = OSC_PLLSRC_XOSC_gc,
68 };
69 
70 #define pll_get_default_rate(pll_id) \
71  pll_get_default_rate_priv(CONFIG_PLL##pll_id##_SOURCE, \
72  CONFIG_PLL##pll_id##_MUL, \
73  CONFIG_PLL##pll_id##_DIV)
74 
89 static inline uint32_t pll_get_default_rate_priv(enum pll_source src,
90  unsigned int mul, unsigned int div)
91 {
92  uint32_t rate;
93 
94  switch (src) {
95  case PLL_SRC_RC2MHZ:
96  rate = 2000000UL;
97  Assert(div == 1);
98  break;
99 
100  case PLL_SRC_RC32MHZ:
101 #ifdef CONFIG_OSC_RC32_CAL //32MHz oscillator is calibrated to another frequency
102  rate = CONFIG_OSC_RC32_CAL / 4;
103 #else
104  rate = 8000000UL;
105  #endif
106  Assert(div == 4);
107  break;
108 
109  case PLL_SRC_XOSC:
110  rate = osc_get_rate(OSC_ID_XOSC);
111  Assert(div == 1);
112  break;
113 
114  default:
115  break;
116  }
117 
118  Assert(rate >= 440000UL);
119 
120  rate *= mul;
121 
122  Assert(rate >= PLL_MIN_HZ);
123  Assert(rate <= PLL_MAX_HZ);
124 
125  return rate;
126 }
127 
128 struct pll_config {
129  uint8_t ctrl;
130 };
131 
138 static inline void pll_config_init(struct pll_config *cfg, enum pll_source src,
139  unsigned int div, unsigned int mul)
140 {
141  Assert(mul >= 1 && mul <= 31);
142 
143  if (src == PLL_SRC_RC32MHZ) {
144  Assert(div == 4);
145  } else {
146  Assert(div == 1);
147  }
148 
149  /* Initialize the configuration */
150  cfg->ctrl = src | (mul << OSC_PLLFAC_gp);
151 }
152 
153 #define pll_config_defaults(cfg, pll_id) \
154  pll_config_init(cfg, \
155  CONFIG_PLL##pll_id##_SOURCE, \
156  CONFIG_PLL##pll_id##_DIV, \
157  CONFIG_PLL##pll_id##_MUL)
158 
159 static inline void pll_config_read(struct pll_config *cfg, unsigned int pll_id)
160 {
161  Assert(pll_id < NR_PLLS);
162 
163  cfg->ctrl = OSC.PLLCTRL;
164 }
165 
166 static inline void pll_config_write(const struct pll_config *cfg,
167  unsigned int pll_id)
168 {
169  Assert(pll_id < NR_PLLS);
170 
171  OSC.PLLCTRL = cfg->ctrl;
172 }
173 
179 static inline void pll_enable(const struct pll_config *cfg,
180  unsigned int pll_id)
181 {
182  irqflags_t flags;
183 
184  Assert(pll_id < NR_PLLS);
185 
186  flags = cpu_irq_save();
187  pll_config_write(cfg, pll_id);
188  OSC.CTRL |= OSC_PLLEN_bm;
189  cpu_irq_restore(flags);
190 }
191 
195 static inline void pll_disable(unsigned int pll_id)
196 {
197  irqflags_t flags;
198 
199  Assert(pll_id < NR_PLLS);
200 
201  flags = cpu_irq_save();
202  OSC.CTRL &= ~OSC_PLLEN_bm;
203  cpu_irq_restore(flags);
204 }
205 
206 static inline bool pll_is_locked(unsigned int pll_id)
207 {
208  Assert(pll_id < NR_PLLS);
209 
210  return OSC.STATUS & OSC_PLLRDY_bm;
211 }
212 
213 static inline void pll_enable_source(enum pll_source src)
214 {
215  switch (src) {
216  case PLL_SRC_RC2MHZ:
217  break;
218 
219  case PLL_SRC_RC32MHZ:
220  if (!osc_is_ready(OSC_ID_RC32MHZ)) {
221  osc_enable(OSC_ID_RC32MHZ);
222  osc_wait_ready(OSC_ID_RC32MHZ);
223 #ifdef CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC
224  if (CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC
225  != OSC_ID_USBSOF) {
226  osc_enable(CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC);
227  osc_wait_ready(CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC);
228  }
230  CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC);
231 #endif
232  }
233  break;
234 
235  case PLL_SRC_XOSC:
236  if (!osc_is_ready(OSC_ID_XOSC)) {
237  osc_enable(OSC_ID_XOSC);
238  osc_wait_ready(OSC_ID_XOSC);
239  }
240  break;
241  default:
242  Assert(false);
243  break;
244  }
245 }
246 
247 static inline void pll_enable_config_defaults(unsigned int pll_id)
248 {
249  struct pll_config pllcfg;
250 
251  if (pll_is_locked(pll_id)) {
252  return; // Pll already running
253  }
254  switch (pll_id) {
255 #ifdef CONFIG_PLL0_SOURCE
256  case 0:
257  pll_enable_source(CONFIG_PLL0_SOURCE);
258  pll_config_init(&pllcfg,
259  CONFIG_PLL0_SOURCE,
260  CONFIG_PLL0_DIV,
261  CONFIG_PLL0_MUL);
262  break;
263 #endif
264  default:
265  Assert(false);
266  break;
267  }
268  pll_enable(&pllcfg, pll_id);
269  while (!pll_is_locked(pll_id));
270 }
271 
272 static inline int pll_wait_for_lock(unsigned int pll_id)
273 {
274  Assert(pll_id < NR_PLLS);
275 
276  while (!pll_is_locked(pll_id)) {
277  /* Do nothing */
278  }
279 
280  return 0;
281 }
282 
283 
285 
286 #endif /* XMEGA_PLL_H_INCLUDED */
#define OSC_ID_RC32MHZ
32 MHz Internal RC Oscillator
Definition: osc.h:66
static void pll_disable(unsigned int pll_id)
Definition: pll.h:195
static void pll_config_init(struct pll_config *cfg, enum pll_source src, unsigned int div, unsigned int mul)
Definition: pll.h:138
pll_source
Definition: pll.h:61
Commonly used includes, types and macros.
#define Assert(expr)
This macro is used to test fatal errors.
Definition: compiler.h:46
static uint32_t pll_get_default_rate_priv(enum pll_source src, unsigned int mul, unsigned int div)
Return clock rate for specified PLL settings.
Definition: pll.h:89
#define OSC_ID_XOSC
External Oscillator.
Definition: osc.h:70
static void osc_enable_autocalibration(uint8_t id, uint8_t ref_id)
Enable DFLL-based automatic calibration of an internal oscillator.
Definition: osc.h:325
2 MHz Internal RC Oscillator
Definition: pll.h:63
32 MHz Internal RC Oscillator
Definition: pll.h:65
static void pll_enable(const struct pll_config *cfg, unsigned int pll_id)
Definition: pll.h:179
#define OSC_ID_USBSOF
Reference from USB Start Of Frame.
Definition: osc.h:81
External Clock Source.
Definition: pll.h:67