fix LPC812 PWM
Fork of mbed-dev by
Diff: targets/cmsis/TARGET_NXP/TARGET_LPC43XX/system_LPC43xx.c
- Revision:
- 0:9b334a45a8ff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/targets/cmsis/TARGET_NXP/TARGET_LPC43XX/system_LPC43xx.c Thu Oct 01 15:25:22 2015 +0300 @@ -0,0 +1,373 @@ +/* + * @brief LPC43xx System Initialization + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + * + * Modified by Micromint USA <support@micromint.com> + */ +#include "LPC43xx.h" + +#define COUNT_OF(a) (sizeof(a)/sizeof(a[0])) + +/* Clock variables */ +#if (CLOCK_SETUP) +uint32_t SystemCoreClock = MAX_CLOCK_FREQ; +#else +uint32_t SystemCoreClock = CRYSTAL_MAIN_FREQ_IN; +#endif + +#if !defined(CORE_M0) +/* SCU pin definitions for pin muxing */ +typedef struct { + __IO uint32_t *reg; /* SCU register address */ + uint16_t mode; /* SCU pin mode and function */ +} PINMUX_GRP_T; + +/* Pins to initialize before clocks are configured */ +static const PINMUX_GRP_T pre_clock_mux[] = { + /* SPIFI pins */ + {SCU_REG(0x3, 3), (SCU_PINIO_FAST | 0x3)}, /* P3_3 SPIFI CLK */ + {SCU_REG(0x3, 4), (SCU_PINIO_FAST | 0x3)}, /* P3_4 SPIFI D3 */ + {SCU_REG(0x3, 5), (SCU_PINIO_FAST | 0x3)}, /* P3_5 SPIFI D2 */ + {SCU_REG(0x3, 6), (SCU_PINIO_FAST | 0x3)}, /* P3_6 SPIFI D1 */ + {SCU_REG(0x3, 7), (SCU_PINIO_FAST | 0x3)}, /* P3_7 SPIFI D0 */ + {SCU_REG(0x3, 8), (SCU_PINIO_FAST | 0x3)} /* P3_8 SPIFI CS/SSEL */ +}; + +/* Pins to initialize after clocks are configured */ +static const PINMUX_GRP_T post_clock_mux[] = { + /* Boot pins */ + {SCU_REG(0x1, 1), (SCU_PINIO_FAST | 0x0)}, /* P1_1 BOOT0 */ + {SCU_REG(0x1, 2), (SCU_PINIO_FAST | 0x0)}, /* P1_2 BOOT1 */ + {SCU_REG(0x2, 8), (SCU_PINIO_FAST | 0x0)}, /* P2_8 BOOT2 */ + {SCU_REG(0x2, 9), (SCU_PINIO_FAST | 0x0)}, /* P2_9 BOOT3 */ + /* Micromint Bambino 200/210 */ + {SCU_REG(0x6, 11), (SCU_PINIO_FAST | 0x0)}, /* P6_11 LED1 */ + {SCU_REG(0x2, 5), (SCU_PINIO_FAST | 0x0)}, /* P2_5 LED2 */ + {SCU_REG(0x2, 7), (SCU_PINIO_FAST | 0x0)}, /* P2_7 BTN1 */ + /* Micromint Bambino 210 */ + {SCU_REG(0x6, 1), (SCU_PINIO_FAST | 0x0)}, /* P6_1 LED3 */ + {SCU_REG(0x6, 2), (SCU_PINIO_FAST | 0x0)}, /* P6_2 LED4 */ +}; + +#if (CLOCK_SETUP) +/* Structure for initial base clock states */ +struct CLK_BASE_STATES { + CGU_BASE_CLK_T clk; /* Base clock */ + CGU_CLKIN_T clkin; /* Base clock source */ + uint8_t powerdn; /* Set to 1 if base clock is initially powered down */ +}; + +/* Initial base clock states are mostly on */ +static const struct CLK_BASE_STATES clock_states[] = { + {CLK_BASE_SAFE, CLKIN_IRC, 0}, + {CLK_BASE_APB1, CLKIN_MAINPLL, 0}, + {CLK_BASE_APB3, CLKIN_MAINPLL, 0}, + {CLK_BASE_USB0, CLKIN_USBPLL, 1}, + {CLK_BASE_PERIPH, CLKIN_MAINPLL, 0}, + {CLK_BASE_SPI, CLKIN_MAINPLL, 0}, + {CLK_BASE_PHY_TX, CLKIN_ENET_TX, 0}, +#if defined(USE_RMII) + {CLK_BASE_PHY_RX, CLKIN_ENET_TX, 0}, +#else + {CLK_BASE_PHY_RX, CLKIN_ENET_RX, 0}, +#endif + {CLK_BASE_SDIO, CLKIN_MAINPLL, 0}, + {CLK_BASE_SSP0, CLKIN_IDIVC, 0}, + {CLK_BASE_SSP1, CLKIN_IDIVC, 0}, + {CLK_BASE_UART0, CLKIN_MAINPLL, 0}, + {CLK_BASE_UART1, CLKIN_MAINPLL, 0}, + {CLK_BASE_UART2, CLKIN_MAINPLL, 0}, + {CLK_BASE_UART3, CLKIN_MAINPLL, 0}, + {CLK_BASE_OUT, CLKINPUT_PD, 0}, + {CLK_BASE_APLL, CLKINPUT_PD, 0}, + {CLK_BASE_CGU_OUT0, CLKINPUT_PD, 0}, + {CLK_BASE_CGU_OUT1, CLKINPUT_PD, 0}, + + /* Clocks derived from dividers */ + {CLK_BASE_LCD, CLKIN_IDIVC, 0}, + {CLK_BASE_USB1, CLKIN_IDIVD, 1} +}; +#endif /* defined(CLOCK_SETUP) */ + +/* Local functions */ +static uint32_t SystemGetMainPLLHz(void); +static void SystemSetupClock(void); +static void SystemSetupPins(const PINMUX_GRP_T *mux, uint32_t n); +static void SystemSetupMemory(void); +static void WaitUs(uint32_t us); + +#endif /* !defined(CORE_M0) */ + +/* + * SystemInit() - Initialize the system + */ +void SystemInit(void) +{ +#if !defined(CORE_M0) + + /* Initialize vector table in flash */ +#if defined(__ARMCC_VERSION) + extern void *__Vectors; + + SCB->VTOR = (unsigned int) &__Vectors; +#elif defined(__IAR_SYSTEMS_ICC__) + extern void *__vector_table; + + SCB->VTOR = (unsigned int) &__vector_table; +#elif defined(TOOLCHAIN_GCC_ARM) + extern void *__isr_vector; + + SCB->VTOR = (unsigned int) &__isr_vector; +#else /* defined(__GNUC__) and others */ + extern void *g_pfnVectors; + + SCB->VTOR = (unsigned int) &g_pfnVectors; +#endif + +#if defined(__FPU_PRESENT) && __FPU_PRESENT == 1 + /* Initialize floating point */ + fpuInit(); +#endif + + SystemSetupPins(pre_clock_mux, COUNT_OF(pre_clock_mux)); /* Configure pins */ + SystemSetupClock(); /* Configure processor and peripheral clocks */ + SystemSetupPins(post_clock_mux, COUNT_OF(post_clock_mux)); /* Configure pins */ + SystemSetupMemory(); /* Configure external memory */ +#endif /* !defined(CORE_M0) */ + + SystemCoreClockUpdate(); /* Update SystemCoreClock variable */ +} + +/* + * SystemCoreClockUpdate() - Update SystemCoreClock variable + */ +void SystemCoreClockUpdate(void) +{ + uint32_t reg, div, rate; + + /* Get main PLL rate */ + rate = SystemGetMainPLLHz(); + + /* Get clock divider */ + reg = LPC_CCU1->CLKCCU[CLK_MX_MXCORE].CFG; + if (((reg >> 5) & 0x7) == 0) { + div = 1; + } + else { + div = 2; + } + rate = rate / div; + + SystemCoreClock = rate; +} + +/* Returns the frequency of the main PLL */ +uint32_t SystemGetMainPLLHz(void) +{ + uint32_t PLLReg = LPC_CGU->PLL1_CTRL; + uint32_t freq = CRYSTAL_MAIN_FREQ_IN; + uint32_t msel, nsel, psel, direct, fbsel; + uint32_t m, n, p; + const uint8_t ptab[] = {1, 2, 4, 8}; + + msel = (PLLReg >> 16) & 0xFF; + nsel = (PLLReg >> 12) & 0x3; + psel = (PLLReg >> 8) & 0x3; + direct = (PLLReg >> 7) & 0x1; + fbsel = (PLLReg >> 6) & 0x1; + + m = msel + 1; + n = nsel + 1; + p = ptab[psel]; + + if (direct || fbsel) { + return m * (freq / n); + } + + return (m / (2 * p)) * (freq / n); +} + +#if !defined(CORE_M0) +/* + * SystemSetupClock() - Set processor and peripheral clocks + * + * Clock Frequency Source + * CLK_BASE_MX 204 MHz CLKIN_MAINPLL (CLKIN_PLL1) + * CLK_BASE_SPIFI 102 MHz CLKIN_IDIVE + * CLK_BASE_USB0 480 MHz CLKIN_USBPLL (Disabled) (CLKIN_PLL0USB) + * CLK_BASE_USB1 60 MHz CLKIN_IDIVE (Disabled) + * 120 MHz CLKIN_IDIVD (Disabled) + * + * 12 MHz CLKIN_IDIVB + * 12 MHz CLKIN_IDIVC + * + */ +void SystemSetupClock(void) +{ +#if (CLOCK_SETUP) + uint32_t i; + + /* Switch main clock to Internal RC (IRC) while setting up PLL1 */ + LPC_CGU->BASE_CLK[CLK_BASE_MX] = (1 << 11) | (CLKIN_IRC << 24); + /* Set prescaler/divider on SSP1 assuming 204 MHz clock */ + LPC_SSP1->CR1 &= ~(1 << 1); + LPC_SSP1->CPSR = 0x0002; + LPC_SSP1->CR0 = 0x00006507; + LPC_SSP1->CR1 |= (1 << 1); + + /* Enable the oscillator and wait 100 us */ + LPC_CGU->XTAL_OSC_CTRL = 0; + WaitUs(100); + +#if (SPIFI_INIT) + /* Setup SPIFI control register and no-opcode mode */ + LPC_SPIFI->CTRL = (0x100 << 0) | (1 << 16) | (1 << 29) | (1 << 30); + LPC_SPIFI->IDATA = 0xA5; + /* Switch IDIVE clock to IRC and connect to SPIFI clock */ + LPC_CGU->IDIV_CTRL[CLK_IDIV_E] = ((1 << 11) | (CLKIN_IRC << 24)); + LPC_CGU->BASE_CLK[CLK_BASE_SPIFI] = ((1 << 11) | (CLKIN_IDIVE << 24)); +#endif /* SPIFI_INIT */ + + /* Configure PLL1 (MAINPLL) for main clock */ + LPC_CGU->PLL1_CTRL |= 1; /* Power down PLL1 */ + + /* Change PLL1 to 108 Mhz (msel=9, 12 MHz*9=108 MHz) */ + LPC_CGU->PLL1_CTRL = (1 << 7) | (0 << 8) | (1 << 11) | (0 << 12) | (8 << 16) + | (CLKIN_MAINPLL << 24); + while (!(LPC_CGU->PLL1_STAT & 1)); /* Wait for PLL1 to lock */ + WaitUs(100); + + /* Change PLL1 to 204 Mhz (msel=17, 12 MHz*17=204 MHz) */ + LPC_CGU->PLL1_CTRL = (1 << 7) | (0 << 8) | (1 << 11) | (0 << 12) | (16 << 16) + | (CLKIN_MAINPLL << 24); + while (!(LPC_CGU->PLL1_STAT & 1)); /* Wait for PLL1 to lock */ + + /* Connect main clock to PLL1 */ + LPC_CGU->BASE_CLK[CLK_BASE_MX] = (1 << 11) | (CLKIN_MAINPLL << 24); + + /* Set USB PLL dividers for 480 MHz (for USB0) */ + LPC_CGU->PLL[CGU_USB_PLL].PLL_MDIV = 0x06167FFA; + LPC_CGU->PLL[CGU_USB_PLL].PLL_NP_DIV = 0x00302062; + LPC_CGU->PLL[CGU_USB_PLL].PLL_CTRL = 0x0000081D | (CLKIN_CRYSTAL << 24); + + /* Set IDIVE clock to PLL1/2 = 102 MHz */ + LPC_CGU->IDIV_CTRL[CLK_IDIV_E] = (1 << 2) | (1 << 11) | (CLKIN_MAINPLL << 24); /* PLL1/2 */ + + /* Set IDIVD clock to ((USBPLL/4) / 2) = 60 MHz (for USB1) */ + LPC_CGU->IDIV_CTRL[CLK_IDIV_A] = (3 << 2) | (1 << 11) | (CLKIN_USBPLL << 24); /* USBPLL/4 */ + LPC_CGU->IDIV_CTRL[CLK_IDIV_D] = (1 << 2) | (1 << 11) | (CLKIN_IDIVA << 24); /* IDIVA/2 */ + + /* Configure remaining integer dividers */ + LPC_CGU->IDIV_CTRL[CLK_IDIV_B] = (0 << 2) | (1 << 11) | (CLKIN_IRC << 24); /* IRC */ + LPC_CGU->IDIV_CTRL[CLK_IDIV_C] = (1 << 2) | (1 << 11) | (CLKIN_MAINPLL << 24); /* PLL1/2 */ + + /* Connect base clocks */ + for (i = 0; i < COUNT_OF(clock_states); i++) { + LPC_CGU->BASE_CLK[clock_states[i].clk] = + ( clock_states[i].powerdn << 0) + | (1 << 11) | (clock_states[i].clkin << 24); + } +#endif /* CLOCK_SETUP */ + /* Reset peripherals */ + LPC_RGU->RESET_CTRL0 = 0x105F0000; + LPC_RGU->RESET_CTRL1 = 0x01DFF7FF; +} + +/* + * SystemSetupPins() - Configure MCU pins + */ +void SystemSetupPins(const PINMUX_GRP_T *mux, uint32_t n) +{ + uint32_t i; + + for (i = 0; i < n; i++) { + *(mux[i].reg) = mux[i].mode; + } +} + +/* + * SystemSetupMemory() - Configure external memory + */ +void SystemSetupMemory(void) +{ +#if (MEMORY_SETUP) + /* None required for boards without external memory */ +#endif /* MEMORY_SETUP */ +} + +#if defined(__FPU_PRESENT) && __FPU_PRESENT == 1 +/* + * fpuInit() - Early initialization of the FPU + */ +void fpuInit(void) +{ + /* + * from ARM TRM manual: + * ; CPACR is located at address 0xE000ED88 + * LDR.W R0, =0xE000ED88 + * ; Read CPACR + * LDR R1, [R0] + * ; Set bits 20-23 to enable CP10 and CP11 coprocessors + * ORR R1, R1, #(0xF << 20) + * ; Write back the modified value to the CPACR + * STR R1, [R0] + */ + + volatile uint32_t *regCpacr = (uint32_t *) LPC_CPACR; + volatile uint32_t *regMvfr0 = (uint32_t *) SCB_MVFR0; + volatile uint32_t *regMvfr1 = (uint32_t *) SCB_MVFR1; + volatile uint32_t Cpacr; + volatile uint32_t Mvfr0; + volatile uint32_t Mvfr1; + char vfpPresent = 0; + + Mvfr0 = *regMvfr0; + Mvfr1 = *regMvfr1; + + vfpPresent = ((SCB_MVFR0_RESET == Mvfr0) && (SCB_MVFR1_RESET == Mvfr1)); + + if (vfpPresent) { + Cpacr = *regCpacr; + Cpacr |= (0xF << 20); + *regCpacr = Cpacr; /* enable CP10 and CP11 for full access */ + } +} +#endif /* defined(__FPU_PRESENT) && __FPU_PRESENT == 1 */ + +/* Approximate delay function */ +#define CPU_NANOSEC(x) (((uint64_t) (x) * SystemCoreClock) / 1000000000) + +static void WaitUs(uint32_t us) +{ + volatile uint32_t cyc = us * CPU_NANOSEC(1000) / 4; + while (cyc--) + ; +} + +#endif /* !defined(CORE_M0) */