Hanna
Sourcecode Batteriemanagementsystem
osc.h
gehe zur Dokumentation dieser Datei
1 
45 #ifndef XMEGA_OSC_H_INCLUDED
46 #define XMEGA_OSC_H_INCLUDED
47 
48 #include <board_init.h>
49 #include <compiler.h>
50 
51 
61 
63 #define OSC_ID_RC2MHZ OSC_RC2MEN_bm
65 #define OSC_ID_RC32MHZ OSC_RC32MEN_bm
67 #define OSC_ID_RC32KHZ OSC_RC32KEN_bm
69 #define OSC_ID_XOSC OSC_XOSCEN_bm
71 #if XMEGA_E
72 # define OSC_ID_RC8MHZ OSC_RC8MEN_bm
74 #endif
75 
81 #define OSC_ID_USBSOF 0xff
82 
83 
85 
86 #define XOSC_TYPE_EXTERNAL 0
87 #define XOSC_TYPE_32KHZ 2
88 #define XOSC_TYPE_XTAL 3
89 
90 
91 
95 #ifdef __DOXYGEN__
96 # define CONFIG_XOSC_32KHZ_LPM
97 #endif /* __DOXYGEN__ */
98 
109 
111 #define XOSC_STARTUP_256 0
112 #define XOSC_STARTUP_1024 1
113 #define XOSC_STARTUP_16384 2
114 
115 
116 
125 
127 #define XOSC_RANGE_04TO2 OSC_FRQRANGE_04TO2_gc
129 #define XOSC_RANGE_2TO9 OSC_FRQRANGE_2TO9_gc
131 #define XOSC_RANGE_9TO12 OSC_FRQRANGE_9TO12_gc
133 #define XOSC_RANGE_12TO16 OSC_FRQRANGE_12TO16_gc
135 
136 
147 // If application intends to use XOSC.
148 #ifdef BOARD_XOSC_HZ
149 // Get start-up config for XOSC, if not manually set.
150 # ifndef CONFIG_XOSC_STARTUP
151 # ifndef BOARD_XOSC_STARTUP_US
152 # error BOARD_XOSC_STARTUP_US must be configured.
153 # else
154 # define BOARD_XOSC_STARTUP_CYCLES \
156  (BOARD_XOSC_HZ / 1000000 * BOARD_XOSC_STARTUP_US)
157 
158 # if (BOARD_XOSC_TYPE == XOSC_TYPE_XTAL)
159 # if (BOARD_XOSC_STARTUP_CYCLES > 16384)
160 # error BOARD_XOSC_STARTUP_US is too high for current BOARD_XOSC_HZ.
161 
162 # elif (BOARD_XOSC_STARTUP_CYCLES > 1024)
163 # define CONFIG_XOSC_STARTUP XOSC_STARTUP_16384
164 # define XOSC_STARTUP_TIMEOUT (16384*(1000000/BOARD_XOSC_HZ))
165 
166 # elif (BOARD_XOSC_STARTUP_CYCLES > 256)
167 # define CONFIG_XOSC_STARTUP XOSC_STARTUP_1024
168 # define XOSC_STARTUP_TIMEOUT (1024*(1000000/BOARD_XOSC_HZ))
169 
170 # else
171 # define CONFIG_XOSC_STARTUP XOSC_STARTUP_256
172 # define XOSC_STARTUP_TIMEOUT (256*(1000000/BOARD_XOSC_HZ))
173 # endif
174 # else /* BOARD_XOSC_TYPE == XOSC_TYPE_XTAL */
175 # define CONFIG_XOSC_STARTUP 0
176 # endif
177 # endif /* BOARD_XOSC_STARTUP_US */
178 # endif /* CONFIG_XOSC_STARTUP */
179 
180 // Get frequency range setting for XOSC, if not manually set.
181 # ifndef CONFIG_XOSC_RANGE
182 # if (BOARD_XOSC_TYPE == XOSC_TYPE_XTAL)
183 # if (BOARD_XOSC_HZ < 400000)
184 # error BOARD_XOSC_HZ is below minimum frequency of 400 kHz.
185 
186 # elif (BOARD_XOSC_HZ < 2000000)
187 # define CONFIG_XOSC_RANGE XOSC_RANGE_04TO2
188 
189 # elif (BOARD_XOSC_HZ < 9000000)
190 # define CONFIG_XOSC_RANGE XOSC_RANGE_2TO9
191 
192 # elif (BOARD_XOSC_HZ < 12000000)
193 # define CONFIG_XOSC_RANGE XOSC_RANGE_9TO12
194 
195 # elif (BOARD_XOSC_HZ <= 16000000)
196 # define CONFIG_XOSC_RANGE XOSC_RANGE_12TO16
197 
198 # else
199 # error BOARD_XOSC_HZ is above maximum frequency of 16 MHz.
200 # endif
201 # else /* BOARD_XOSC_TYPE == XOSC_TYPE_XTAL */
202 # define CONFIG_XOSC_RANGE 0
203 # endif
204 # endif /* CONFIG_XOSC_RANGE */
205 #endif /* BOARD_XOSC_HZ */
206 
207 #ifndef __ASSEMBLY__
208 
215 static inline void osc_enable_internal(uint8_t id)
216 {
217  irqflags_t flags;
218 
219  Assert(id != OSC_ID_USBSOF);
220 
221  flags = cpu_irq_save();
222  OSC.CTRL |= id;
223 #if (XMEGA_E && CONFIG_SYSCLK_RC8MHZ_LPM)
224  if(id == OSC_ID_RC8MHZ) {
225  OSC.CTRL |= OSC_RC8MLPM_bm;
226  }
227 #endif
228  cpu_irq_restore(flags);
229 }
230 
231 #if defined(BOARD_XOSC_HZ) || defined(__DOXYGEN__)
232 
241 static inline void osc_enable_external(uint8_t id)
242 {
243  irqflags_t flags;
244 
245  Assert(id == OSC_ID_XOSC);
246 
247 #ifndef CONFIG_XOSC_32KHZ_LPM
248 # if (XMEGA_E && (BOARD_XOSC_TYPE == XOSC_TYPE_EXTERNAL) && defined(CONFIG_XOSC_EXTERNAL_PC4))
249  OSC.XOSCCTRL = OSC_XOSCSEL4_bm;
250 # else
251  OSC.XOSCCTRL = BOARD_XOSC_TYPE | (CONFIG_XOSC_STARTUP << 2) |
252  CONFIG_XOSC_RANGE;
253 # endif
254 #else
255  OSC.XOSCCTRL = BOARD_XOSC_TYPE | (CONFIG_XOSC_STARTUP << 2) |
256  CONFIG_XOSC_RANGE | OSC_X32KLPM_bm;
257 #endif /* CONFIG_XOSC_32KHZ_LPM */
258 
259  flags = cpu_irq_save();
260  OSC.CTRL |= id;
261  cpu_irq_restore(flags);
262 }
263 #else
264 
265 static inline void osc_enable_external(uint8_t id)
266 {
267  Assert(false); // No external oscillator on the selected board
268 }
269 #endif
270 
271 static inline void osc_disable(uint8_t id)
272 {
273  irqflags_t flags;
274 
275  Assert(id != OSC_ID_USBSOF);
276 
277  flags = cpu_irq_save();
278  OSC.CTRL &= ~id;
279  cpu_irq_restore(flags);
280 }
281 
282 static inline void osc_enable(uint8_t id)
283 {
284  if (id != OSC_ID_XOSC) {
286  } else {
287  osc_enable_external(id);
288  }
289 }
290 
291 static inline bool osc_is_ready(uint8_t id)
292 {
293  Assert(id != OSC_ID_USBSOF);
294 
295  return OSC.STATUS & id;
296 }
297 
299 
300 
325 static inline void osc_enable_autocalibration(uint8_t id, uint8_t ref_id)
326 {
327  irqflags_t flags;
328 
329  flags = cpu_irq_save();
330  switch (id) {
331  case OSC_ID_RC2MHZ:
332 #if !XMEGA_E
333  Assert((ref_id == OSC_ID_RC32KHZ) || (ref_id == OSC_ID_XOSC));
334  if (ref_id == OSC_ID_XOSC) {
335  osc_enable(OSC_ID_RC32KHZ);
336  OSC.DFLLCTRL |= OSC_RC2MCREF_bm;
337  } else {
338  OSC.DFLLCTRL &= ~(OSC_RC2MCREF_bm);
339  }
340  DFLLRC2M.CTRL |= DFLL_ENABLE_bm;
341 #endif
342  break;
343 
344  case OSC_ID_RC32MHZ:
345 #if XMEGA_AU || XMEGA_B || XMEGA_C || XMEGA_E
346  Assert((ref_id == OSC_ID_RC32KHZ)
347  || (ref_id == OSC_ID_XOSC)
348 # if !XMEGA_E
349  || (ref_id == OSC_ID_USBSOF)
350 #endif
351  );
352 
353  OSC.DFLLCTRL &= ~(OSC_RC32MCREF_gm);
354 
355  if (ref_id == OSC_ID_XOSC) {
356  osc_enable(OSC_ID_RC32KHZ);
357  OSC.DFLLCTRL |= OSC_RC32MCREF_XOSC32K_gc;
358  }
359  else if (ref_id == OSC_ID_RC32KHZ) {
360  OSC.DFLLCTRL |= OSC_RC32MCREF_RC32K_gc;
361  }
362 # if !XMEGA_E
363  else if (ref_id == OSC_ID_USBSOF) {
364  /*
365  * Calibrate 32MRC at 48MHz using USB SOF
366  * 48MHz / 1kHz = 0xBB80
367  */
368  DFLLRC32M.COMP1 = 0x80;
369  DFLLRC32M.COMP2 = 0xBB;
370  OSC.DFLLCTRL |= OSC_RC32MCREF_USBSOF_gc;
371  }
372 # endif
373 #else
374  Assert((ref_id == OSC_ID_RC32KHZ) ||
375  (ref_id == OSC_ID_XOSC));
376 
377 # if defined(OSC_RC32MCREF_gm)
378  OSC.DFLLCTRL &= ~(OSC_RC32MCREF_gm);
379 # endif
380 
381  if (ref_id == OSC_ID_XOSC) {
382  osc_enable(OSC_ID_RC32KHZ);
383 # if defined(OSC_RC32MCREF_gm)
384  OSC.DFLLCTRL |= OSC_RC32MCREF_XOSC32K_gc;
385 # else
386  OSC.DFLLCTRL |= OSC_RC32MCREF_bm;
387 # endif
388  }
389  else if (ref_id == OSC_ID_RC32KHZ) {
390 # if defined(OSC_RC32MCREF_gm)
391  OSC.DFLLCTRL |= OSC_RC32MCREF_RC32K_gc;
392 # else
393  OSC.DFLLCTRL &= ~(OSC_RC32MCREF_bm);
394 # endif
395  }
396 #endif
397 
398  DFLLRC32M.CTRL |= DFLL_ENABLE_bm;
399  break;
400 
401  default:
402  Assert(false);
403  break;
404  }
405  cpu_irq_restore(flags);
406 }
407 
418 static inline void osc_disable_autocalibration(uint8_t id)
419 {
420  switch (id) {
421  case OSC_ID_RC2MHZ:
422 #if !XMEGA_E
423  DFLLRC2M.CTRL = 0;
424 #endif
425  break;
426 
427  case OSC_ID_RC32MHZ:
428  DFLLRC32M.CTRL = 0;
429  break;
430 
431  default:
432  Assert(false);
433  break;
434  }
435 }
436 
446 static inline void osc_user_calibration(uint8_t id, uint16_t calib)
447 {
448  switch (id) {
449  case OSC_ID_RC2MHZ:
450 #if !XMEGA_E
451  DFLLRC2M.CALA=LSB(calib);
452  DFLLRC2M.CALB=MSB(calib);
453 #endif
454  break;
455 
456  case OSC_ID_RC32MHZ:
457  DFLLRC32M.CALA=LSB(calib);
458  DFLLRC32M.CALB=MSB(calib);
459  break;
460 
461 #if XMEGA_E
462  case OSC_ID_RC8MHZ:
463  OSC.RC8MCAL=LSB(calib);
464  break;
465 #endif
466 
467  default:
468  Assert(false);
469  break;
470  }
471 }
473 
474 static inline uint32_t osc_get_rate(uint8_t id)
475 {
476  Assert(id != OSC_ID_USBSOF);
477 
478  switch (id) {
479  case OSC_ID_RC2MHZ:
480  return 2000000UL;
481 
482  case OSC_ID_RC32MHZ:
483 #ifdef CONFIG_OSC_RC32_CAL
484  return CONFIG_OSC_RC32_CAL;
485 #else
486  return 32000000UL;
487 #endif
488 
489  case OSC_ID_RC32KHZ:
490  return 32768UL;
491 
492 #ifdef BOARD_XOSC_HZ
493  case OSC_ID_XOSC:
494  return BOARD_XOSC_HZ;
495 #endif
496 
497  default:
498  Assert(false);
499  return 0;
500  }
501 }
502 
503 static inline void osc_wait_ready(uint8_t id)
504 {
505  while (!osc_is_ready(id)) {
506  /* Do nothing */
507  }
508 }
509 
510 
511 #endif /* __ASSEMBLY__ */
512 
514 
515 #endif /* XMEGA_OSC_H_INCLUDED */
#define OSC_ID_RC32MHZ
32 MHz Internal RC Oscillator
Definition: osc.h:66
Standard board header file. Diese Datei enthält die Standardparameter und Pinbelegungen für das BMS B...
Commonly used includes, types and macros.
#define Assert(expr)
This macro is used to test fatal errors.
Definition: compiler.h:46
#define OSC_ID_RC2MHZ
2 MHz Internal RC Oscillator
Definition: osc.h:64
static void osc_disable_autocalibration(uint8_t id)
Disable DFLL-based automatic calibration of an internal oscillator.
Definition: osc.h:418
#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
static void osc_user_calibration(uint8_t id, uint16_t calib)
Load a specific calibration value for the specified oscillator.
Definition: osc.h:446
#define OSC_ID_RC32KHZ
32 KHz Internal RC Oscillator
Definition: osc.h:68
#define OSC_ID_USBSOF
Reference from USB Start Of Frame.
Definition: osc.h:81
static void osc_enable_internal(uint8_t id)
Enable internal oscillator id.
Definition: osc.h:215