summaryrefslogtreecommitdiffstats
path: root/bsps/arm/lpc24xx/start/system-clocks.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/arm/lpc24xx/start/system-clocks.c')
-rw-r--r--bsps/arm/lpc24xx/start/system-clocks.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/bsps/arm/lpc24xx/start/system-clocks.c b/bsps/arm/lpc24xx/start/system-clocks.c
new file mode 100644
index 0000000000..f64fca1bed
--- /dev/null
+++ b/bsps/arm/lpc24xx/start/system-clocks.c
@@ -0,0 +1,167 @@
+/**
+ * @file
+ *
+ * @ingroup lpc24xx_clocks
+ *
+ * @brief System clocks.
+ */
+
+/*
+ * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/counter.h>
+
+#include <bsp.h>
+#include <bsp/lpc24xx.h>
+#include <bsp/system-clocks.h>
+
+/**
+ * @brief Internal RC oscillator frequency in [Hz].
+ */
+#define LPC24XX_OSCILLATOR_INTERNAL 4000000U
+
+#ifndef LPC24XX_OSCILLATOR_MAIN
+ #error "unknown main oscillator frequency"
+#endif
+
+#ifndef LPC24XX_OSCILLATOR_RTC
+ #error "unknown RTC oscillator frequency"
+#endif
+
+void lpc24xx_timer_initialize(void)
+{
+ /* Reset timer */
+ T1TCR = TCR_RST;
+
+ /* Set timer mode */
+ T1CTCR = 0;
+
+ /* Set prescaler to zero */
+ T1PR = 0;
+
+ /* Reset all interrupt flags */
+ T1IR = 0xff;
+
+ /* Do not stop on a match */
+ T1MCR = 0;
+
+ /* No captures */
+ T1CCR = 0;
+
+ /* Start timer */
+ T1TCR = TCR_EN;
+
+ rtems_counter_initialize_converter(LPC24XX_PCLK);
+}
+
+CPU_Counter_ticks _CPU_Counter_read(void)
+{
+ return lpc24xx_timer();
+}
+
+void lpc24xx_micro_seconds_delay(unsigned us)
+{
+ unsigned start = lpc24xx_timer();
+ unsigned delay = us * (LPC24XX_PCLK / 1000000);
+ unsigned elapsed = 0;
+
+ do {
+ elapsed = lpc24xx_timer() - start;
+ } while (elapsed < delay);
+}
+
+#ifdef ARM_MULTILIB_ARCH_V7M
+ static unsigned lpc17xx_sysclk(unsigned clksrcsel)
+ {
+ return (clksrcsel & LPC17XX_SCB_CLKSRCSEL_CLKSRC) != 0 ?
+ LPC24XX_OSCILLATOR_MAIN
+ : LPC24XX_OSCILLATOR_INTERNAL;
+ }
+#endif
+
+unsigned lpc24xx_pllclk(void)
+{
+ #ifdef ARM_MULTILIB_ARCH_V4
+ unsigned clksrc = GET_CLKSRCSEL_CLKSRC(CLKSRCSEL);
+ unsigned pllinclk = 0;
+ unsigned pllclk = 0;
+
+ /* Get PLL input frequency */
+ switch (clksrc) {
+ case 0:
+ pllinclk = LPC24XX_OSCILLATOR_INTERNAL;
+ break;
+ case 1:
+ pllinclk = LPC24XX_OSCILLATOR_MAIN;
+ break;
+ case 2:
+ pllinclk = LPC24XX_OSCILLATOR_RTC;
+ break;
+ default:
+ return 0;
+ }
+
+ /* Get PLL output frequency */
+ if ((PLLSTAT & PLLSTAT_PLLC) != 0) {
+ uint32_t pllcfg = PLLCFG;
+ unsigned n = GET_PLLCFG_NSEL(pllcfg) + 1;
+ unsigned m = GET_PLLCFG_MSEL(pllcfg) + 1;
+
+ pllclk = (pllinclk / n) * 2 * m;
+ } else {
+ pllclk = pllinclk;
+ }
+ #else
+ volatile lpc17xx_scb *scb = &LPC17XX_SCB;
+ unsigned sysclk = lpc17xx_sysclk(scb->clksrcsel);
+ unsigned pllstat = scb->pll_0.stat;
+ unsigned pllclk = 0;
+ unsigned enabled_and_locked = LPC17XX_PLL_STAT_PLLE
+ | LPC17XX_PLL_STAT_PLOCK;
+
+ if ((pllstat & enabled_and_locked) == enabled_and_locked) {
+ unsigned m = LPC17XX_PLL_SEL_MSEL_GET(pllstat) + 1;
+
+ pllclk = sysclk * m;
+ }
+ #endif
+
+ return pllclk;
+}
+
+unsigned lpc24xx_cclk(void)
+{
+ #ifdef ARM_MULTILIB_ARCH_V4
+ /* Get PLL output frequency */
+ unsigned pllclk = lpc24xx_pllclk();
+
+ /* Get CPU frequency */
+ unsigned cclk = pllclk / (GET_CCLKCFG_CCLKSEL(CCLKCFG) + 1);
+ #else
+ volatile lpc17xx_scb *scb = &LPC17XX_SCB;
+ unsigned cclksel = scb->cclksel;
+ unsigned cclk_in = 0;
+ unsigned cclk = 0;
+
+ if ((cclksel & LPC17XX_SCB_CCLKSEL_CCLKSEL) != 0) {
+ cclk_in = lpc24xx_pllclk();
+ } else {
+ cclk_in = lpc17xx_sysclk(scb->clksrcsel);
+ }
+
+ cclk = cclk_in / LPC17XX_SCB_CCLKSEL_CCLKDIV_GET(cclksel);
+ #endif
+
+ return cclk;
+}