Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:04

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSBSPsARMLPC24XX_clocks
0007  *
0008  * @brief System clocks.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2008, 2014 embedded brains GmbH & Co. KG
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #include <rtems/counter.h>
0037 
0038 #include <bsp.h>
0039 #include <bsp/lpc24xx.h>
0040 #include <bsp/system-clocks.h>
0041 
0042 /**
0043  * @brief Internal RC oscillator frequency in [Hz].
0044  */
0045 #define LPC24XX_OSCILLATOR_INTERNAL 4000000U
0046 
0047 #ifndef LPC24XX_OSCILLATOR_MAIN
0048   #error "unknown main oscillator frequency"
0049 #endif
0050 
0051 #ifndef LPC24XX_OSCILLATOR_RTC
0052   #error "unknown RTC oscillator frequency"
0053 #endif
0054 
0055 void lpc24xx_timer_initialize(void)
0056 {
0057   /* Reset timer */
0058   T1TCR = TCR_RST;
0059 
0060   /* Set timer mode */
0061   T1CTCR = 0;
0062 
0063   /* Set prescaler to zero */
0064   T1PR = 0;
0065 
0066   /* Reset all interrupt flags */
0067   T1IR = 0xff;
0068 
0069   /* Do not stop on a match */
0070   T1MCR = 0;
0071 
0072   /* No captures */
0073   T1CCR = 0;
0074 
0075   /* Start timer */
0076   T1TCR = TCR_EN;
0077 }
0078 
0079 uint32_t _CPU_Counter_frequency(void)
0080 {
0081   return LPC24XX_PCLK;
0082 }
0083 
0084 CPU_Counter_ticks _CPU_Counter_read(void)
0085 {
0086   return lpc24xx_timer();
0087 }
0088 
0089 void lpc24xx_micro_seconds_delay(unsigned us)
0090 {
0091   unsigned start = lpc24xx_timer();
0092   unsigned delay = us * (LPC24XX_PCLK / 1000000);
0093   unsigned elapsed = 0;
0094 
0095   do {
0096     elapsed = lpc24xx_timer() - start;
0097   } while (elapsed < delay);
0098 }
0099 
0100 #ifdef ARM_MULTILIB_ARCH_V7M
0101   static unsigned lpc17xx_sysclk(unsigned clksrcsel)
0102   {
0103     return (clksrcsel & LPC17XX_SCB_CLKSRCSEL_CLKSRC) != 0 ?
0104       LPC24XX_OSCILLATOR_MAIN
0105         : LPC24XX_OSCILLATOR_INTERNAL;
0106   }
0107 #endif
0108 
0109 unsigned lpc24xx_pllclk(void)
0110 {
0111   #ifdef ARM_MULTILIB_ARCH_V4
0112     unsigned clksrc = GET_CLKSRCSEL_CLKSRC(CLKSRCSEL);
0113     unsigned pllinclk = 0;
0114     unsigned pllclk = 0;
0115 
0116     /* Get PLL input frequency */
0117     switch (clksrc) {
0118       case 0:
0119         pllinclk = LPC24XX_OSCILLATOR_INTERNAL;
0120         break;
0121       case 1:
0122         pllinclk = LPC24XX_OSCILLATOR_MAIN;
0123         break;
0124       case 2:
0125         pllinclk = LPC24XX_OSCILLATOR_RTC;
0126         break;
0127       default:
0128         return 0;
0129     }
0130 
0131     /* Get PLL output frequency */
0132     if ((PLLSTAT & PLLSTAT_PLLC) != 0) {
0133       uint32_t pllcfg = PLLCFG;
0134       unsigned n = GET_PLLCFG_NSEL(pllcfg) + 1;
0135       unsigned m = GET_PLLCFG_MSEL(pllcfg) + 1;
0136 
0137       pllclk = (pllinclk / n) * 2 * m;
0138     } else {
0139       pllclk = pllinclk;
0140     }
0141   #else
0142     volatile lpc17xx_scb *scb = &LPC17XX_SCB;
0143     unsigned sysclk = lpc17xx_sysclk(scb->clksrcsel);
0144     unsigned pllstat = scb->pll_0.stat;
0145     unsigned pllclk = 0;
0146     unsigned enabled_and_locked = LPC17XX_PLL_STAT_PLLE
0147       | LPC17XX_PLL_STAT_PLOCK;
0148 
0149     if ((pllstat & enabled_and_locked) == enabled_and_locked) {
0150       unsigned m = LPC17XX_PLL_SEL_MSEL_GET(pllstat) + 1;
0151 
0152       pllclk = sysclk * m;
0153     }
0154   #endif
0155 
0156   return pllclk;
0157 }
0158 
0159 unsigned lpc24xx_cclk(void)
0160 {
0161   #ifdef ARM_MULTILIB_ARCH_V4
0162     /* Get PLL output frequency */
0163     unsigned pllclk = lpc24xx_pllclk();
0164 
0165     /* Get CPU frequency */
0166     unsigned cclk = pllclk / (GET_CCLKCFG_CCLKSEL(CCLKCFG) + 1);
0167   #else
0168     volatile lpc17xx_scb *scb = &LPC17XX_SCB;
0169     unsigned cclksel = scb->cclksel;
0170     unsigned cclk_in = 0;
0171     unsigned cclk = 0;
0172 
0173     if ((cclksel & LPC17XX_SCB_CCLKSEL_CCLKSEL) != 0) {
0174       cclk_in = lpc24xx_pllclk();
0175     } else {
0176       cclk_in = lpc17xx_sysclk(scb->clksrcsel);
0177     }
0178 
0179     cclk = cclk_in / LPC17XX_SCB_CCLKSEL_CCLKDIV_GET(cclksel);
0180   #endif
0181 
0182   return cclk;
0183 }