You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
213 lines
7.3 KiB
213 lines
7.3 KiB
2 years ago
|
/**************************************************************************//**
|
||
|
* @file system.c
|
||
|
* @brief CMSIS Device System Source File for
|
||
|
* NXP LPC80xm Device Series
|
||
|
* @version V1.0
|
||
|
* @date 01. April 2017
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Important!
|
||
|
// Please configure the desired initial clock setup for your project in:
|
||
|
// $proj_name/inc/chip_setup.h
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
#include <stdint.h>
|
||
|
#include "LPC8xx.h"
|
||
|
#include "swm.h"
|
||
|
#include "syscon.h"
|
||
|
#include "iocon.h"
|
||
|
#include "fro.h"
|
||
|
#include "rom_api.h"
|
||
|
#include "chip_setup.h"
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Validate the the user's selctions
|
||
|
//----------------------------------------------------------------------------
|
||
|
#define CHECK_RANGE(val, min, max) ((val < min) || (val > max))
|
||
|
#define CHECK_RSVD(val, mask) (val & mask)
|
||
|
|
||
|
#if (CHECK_RANGE((FRO_FREQ_VAL), 0, 2))
|
||
|
#error "FRO_FREQ_VAL: Value out of range."
|
||
|
#endif
|
||
|
|
||
|
#if (CHECK_RSVD((MAINCLKSEL_VAL), ~0x00000003))
|
||
|
#error "MAINCLKSEL: Invalid values of reserved bits!"
|
||
|
#endif
|
||
|
|
||
|
#if (CHECK_RANGE((SYSAHBCLKDIV_VAL), 0, 255))
|
||
|
#error "SYSAHBCLKDIV: Value out of range!"
|
||
|
#endif
|
||
|
|
||
|
#if (CHECK_RANGE(CLKIN_CLK_VAL, 1000000, 25000000))
|
||
|
#error "CLKIN frequency is out of bounds"
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Calculate internal clock node frequency initial values
|
||
|
//----------------------------------------------------------------------------
|
||
|
#define __LPOSC_CLK (1000000)
|
||
|
|
||
|
// determine output of the FRO_CLKDIV subsystem
|
||
|
#if FRO_FREQ_VAL == 0
|
||
|
#define __FRO_OSCOUT (18000000)
|
||
|
#elif FRO_FREQ_VAL == 2
|
||
|
#define __FRO_OSCOUT (30000000)
|
||
|
#else
|
||
|
#define __FRO_OSCOUT (24000000)
|
||
|
#endif
|
||
|
|
||
|
#define __FRO_DIVIDERS_OUT (__FRO_OSCOUT / 2)
|
||
|
|
||
|
#define __FRO_CLK __FRO_DIVIDERS_OUT
|
||
|
|
||
|
#define __FRO_DIV_CLK (__FRO_CLK / 2)
|
||
|
|
||
|
// determine external_clk
|
||
|
#define __SYS_OSC_CLK (0)
|
||
|
#define __CLKIN_CLK (CLKIN_CLK_VAL)
|
||
|
#define __EXTERNAL_CLK __CLKIN_CLK
|
||
|
|
||
|
// determine main_clk
|
||
|
#if MAINCLKSEL_VAL == 0
|
||
|
#define __MAIN_CLK __FRO_CLK
|
||
|
#elif MAINCLKSEL_VAL == 1
|
||
|
#define __MAIN_CLK __EXTERNAL_CLK
|
||
|
#elif MAINCLKSEL_VAL == 2
|
||
|
#define __MAIN_CLK __LPOSC_CLK
|
||
|
#else
|
||
|
#define __MAIN_CLK __FRO_DIV_CLK
|
||
|
#endif
|
||
|
|
||
|
// determine system_ahb_clk
|
||
|
#define __SYSTEM_AHB_CLK (__MAIN_CLK / SYSAHBCLKDIV_VAL)
|
||
|
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Function name: SystemInit
|
||
|
// Sets up the initial chip clocking based on MACROs defined in chip_setup.h.
|
||
|
//----------------------------------------------------------------------------
|
||
|
void SystemInit (void) {
|
||
|
|
||
|
uint32_t i;
|
||
|
|
||
|
for (i = 1; i < 1; i++) __NOP(); // To avoid a warning if variable i is unused
|
||
|
|
||
|
// Enable clocks to IOCON and SWM upon entry, disable them upon exit
|
||
|
LPC_SYSCON->SYSAHBCLKCTRL[0] |= (SWM | IOCON);
|
||
|
|
||
|
// Step 0. Configure the FRO subsystem (choose the source for clocks fro and fro_div)
|
||
|
#if (FRO_FREQ_VAL == 0)
|
||
|
//temp |= (FRO_18MHZ << FRO_FREQ_SEL);
|
||
|
LPC_PWRD_API->set_fro_frequency(18000);
|
||
|
#elif (FRO_FREQ_VAL == 2)
|
||
|
//temp |= (FRO_30MHZ << FRO_FREQ_SEL);
|
||
|
LPC_PWRD_API->set_fro_frequency(30000);
|
||
|
#else
|
||
|
//temp |= (FRO_24MHZ << FRO_FREQ_SEL);
|
||
|
LPC_PWRD_API->set_fro_frequency(24000);
|
||
|
#endif
|
||
|
//temp = LPC_SYSCON->FROOSCCTRL; // Get the current register contents
|
||
|
//temp &= ~(FRO_FREQSEL_MASK); // Preserve all but the bits of interest [1:0]
|
||
|
///PC_SYSCON->FROOSCCTRL = temp; // Update the actual register
|
||
|
//LPC_SYSCON->FRODIRECTCLKUEN = 0; // Toggle the update register for the output mux
|
||
|
//LPC_SYSCON->FRODIRECTCLKUEN = 1;
|
||
|
//while (!(LPC_SYSCON->FRODIRECTCLKUEN & 1)) __NOP(); // Wait for update to take effect
|
||
|
|
||
|
// Configure clk_in, if needed for main_clk or other (e.g. clock out, ADC clk.)
|
||
|
#if ((MAINCLKSEL_VAL == 1) || (EXT_CLOCK_FORCE_ENABLE == 1))
|
||
|
LPC_IOCON->PIO0_1 &= (IOCON_MODE_MASK | MODE_INACTIVE); // Disable pull-up and pull-down
|
||
|
LPC_SWM->PINENABLE0 &= ~(CLKIN); // Enable CLKIN func.
|
||
|
#endif
|
||
|
|
||
|
// Step 2. Power up the LP OSC if it's needed for main_clk
|
||
|
#if (MAINCLKSEL_VAL == 2)
|
||
|
LPC_SYSCON->PDRUNCFG &= ~(LPOSC_PD); // Power up the LP OSC
|
||
|
for (i = 0; i < 200; i++) __NOP(); // Wait for osc to stabilize
|
||
|
#endif
|
||
|
|
||
|
// Step 4. Choose source for main_clk
|
||
|
LPC_SYSCON->MAINCLKSEL = MAINCLKSEL_VAL; // Update the actual register
|
||
|
LPC_SYSCON->MAINCLKUEN = 0; // Toggle update register
|
||
|
LPC_SYSCON->MAINCLKUEN = 1;
|
||
|
while (!(LPC_SYSCON->MAINCLKUEN & 1)) __NOP(); // Wait until updated
|
||
|
|
||
|
// Step 6. Configure the main_clock divider
|
||
|
LPC_SYSCON->SYSAHBCLKDIV = SYSAHBCLKDIV_VAL; // Update the actual register
|
||
|
|
||
|
LPC_SYSCON->SYSAHBCLKCTRL[0] &= ~(SWM | IOCON); // Turn off peripheral clocks before leaving
|
||
|
|
||
|
} // end of SystemInit
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Global clock variable declarations and initial value assignments
|
||
|
//----------------------------------------------------------------------------
|
||
|
uint32_t main_clk = __MAIN_CLK;
|
||
|
uint32_t lposc_clk = __LPOSC_CLK;
|
||
|
uint32_t fro_clk = __FRO_CLK;
|
||
|
uint32_t fro_div_clk = __FRO_DIV_CLK;
|
||
|
uint32_t system_ahb_clk = __SYSTEM_AHB_CLK;
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Function name: SystemCoreClockUpdate
|
||
|
// Determines the actual system_ahb_clk (core clock), main_clock,
|
||
|
// fro_clk, and fro_div_clk frequencies
|
||
|
// based on the current state of the device, and updates the associated
|
||
|
// global clock variables.
|
||
|
//----------------------------------------------------------------------------
|
||
|
void SystemCoreClockUpdate (void)
|
||
|
{
|
||
|
uint32_t external_clk;
|
||
|
uint32_t fro_oscout, fro_clock;
|
||
|
uint32_t temp;
|
||
|
|
||
|
// Set the fro_clk and fro_div_clk variables according to current register settings
|
||
|
temp = LPC_SYSCON->FROOSCCTRL;
|
||
|
switch (temp & FRO_FREQSEL_MASK) {
|
||
|
case 0: fro_oscout = 18000000; break;
|
||
|
case 1: fro_oscout = 24000000; break;
|
||
|
default:fro_oscout = 30000000; break;
|
||
|
}
|
||
|
fro_clock = 0;
|
||
|
if ((LPC_SYSCON->PDRUNCFG & (FROOUT_PD | FRO_PD)) == 0x0) {
|
||
|
fro_clock = fro_oscout;
|
||
|
}
|
||
|
fro_clk = fro_clock / 2;
|
||
|
fro_div_clk = fro_clk / 2;
|
||
|
|
||
|
// Set the external_clk variable according to current register values
|
||
|
//if (LPC_SYSCON->EXTCLKSEL == 0)
|
||
|
// external_clk = __SYS_OSC_CLK;
|
||
|
//else
|
||
|
external_clk = __CLKIN_CLK;
|
||
|
|
||
|
// Set the lposc_clk variable
|
||
|
if (!(LPC_SYSCON->PDRUNCFG & LPOSC_PD)) {
|
||
|
lposc_clk = __LPOSC_CLK;
|
||
|
}
|
||
|
else {
|
||
|
lposc_clk = 0;
|
||
|
}
|
||
|
|
||
|
// Set the main_clk variable according to current register values
|
||
|
switch (LPC_SYSCON->MAINCLKSEL & 0x3) {
|
||
|
case 0: main_clk = fro_clk; break;
|
||
|
case 1: main_clk = external_clk; break;
|
||
|
case 2: main_clk = lposc_clk; break;
|
||
|
case 3: main_clk = fro_div_clk; break;
|
||
|
}
|
||
|
|
||
|
// Set the system_ahb_clk (a.k.a SystemCoreClock) variable according to current register values
|
||
|
system_ahb_clk = main_clk / LPC_SYSCON->SYSAHBCLKDIV;
|
||
|
|
||
|
} // end of SystemCoreClockUpdate
|