-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
202 lines (164 loc) · 7.62 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/** \file main.c
* \brief Sample LPC1114 project
* \details This file holds a very basic code for LPC1114. This code configures
* flash access time, enables the PLL and all required clocks and peripherals
* to achieve the highest allowed frequency for LPC1114 (50MHz). Main code
* block just blinks the LED. The LED port and pin are defined in config.h
* file. Target core frequency and quartz crystal resonator frequency are
* defined there as well.
*
* \author Freddie Chopin, http://www.freddiechopin.info/
* \date 2012-01-08
*/
/******************************************************************************
* project: lpc1114_blink_led
* chip: LPC1114
* compiler: arm-none-eabi-gcc (Sourcery CodeBench Lite 2011.09-69) 4.6.1
*
* prefix: (none)
*
* available global functions:
* int main(void)
*
* available local functions:
* static void flash_access_time(uint32_t frequency)
* static uint32_t pll_start(uint32_t crystal, uint32_t frequency)
* static void system_init(void)
*
* available interrupt handlers:
******************************************************************************/
/*
+=============================================================================+
| includes
+=============================================================================+
*/
#include <stdint.h>
#include "inc/LPC11xx.h"
#include "config.h"
#include "hdr/hdr_syscon.h"
/*
+=============================================================================+
| module variables
+=============================================================================+
*/
/*
+=============================================================================+
| local functions' declarations
+=============================================================================+
*/
static void flash_access_time(uint32_t frequency);
static uint32_t pll_start(uint32_t crystal, uint32_t frequency);
static void system_init(void);
/*
+=============================================================================+
| global functions
+=============================================================================+
*/
/*------------------------------------------------------------------------*//**
* \brief main code block
* \details Call some static initialization functions and blink the led with
* frequency defined via count_max variable.
*//*-------------------------------------------------------------------------*/
int main(void)
{
volatile uint32_t count, count_max = 1000000; // with core frequency ~50MHz this gives ~1.5Hz blinking frequency
pll_start(CRYSTAL, FREQUENCY); // start the PLL
system_init(); // initialize other necessary elements
LED_GPIO->DIR |= LED; // set the direction of the LED pin to output
while (1)
{
for (count = 0; count < count_max; count++); // delay
LED_gma = LED; // instead of LED_GPIO->DATA |= LED;
for (count = 0; count < count_max; count++); // delay
LED_gma = 0; // instead of LED_GPIO->DATA &= ~LED;
}
}
/*
+=============================================================================+
| local functions
+=============================================================================+
*/
/*------------------------------------------------------------------------*//**
* \brief Configures flash access time.
* \details Configures flash access time which allows the chip to run at higher
* speeds.
*
* \param [in] frequency defines the target frequency of the core
*//*-------------------------------------------------------------------------*/
static void flash_access_time(uint32_t frequency)
{
uint32_t access_time, flashcfg_register;
if (frequency < 20000000ul) // 1 system clock for core speed below 20MHz
access_time = FLASHCFG_FLASHTIM_1CLK;
else if (frequency < 40000000ul) // 2 system clocks for core speed between 20MHz and 40MHz
access_time = FLASHCFG_FLASHTIM_2CLK;
else // 3 system clocks for core speed over 40MHz
access_time = FLASHCFG_FLASHTIM_3CLK;
// do not modify reserved bits in FLASHCFG register
flashcfg_register = FLASHCFG; // read register
flashcfg_register &= ~(FLASHCFG_FLASHTIM_mask << FLASHCFG_FLASHTIM_bit); // mask the FLASHTIM field
flashcfg_register |= access_time << FLASHCFG_FLASHTIM_bit; // use new FLASHTIM value
FLASHCFG = flashcfg_register; // save the new value back to the register
}
/*------------------------------------------------------------------------*//**
* \brief Starts the PLL.
* \details Configure and enable PLL to achieve some frequency with some
* crystal. Before the speed change flash access time is configured via
* flash_access_time(). Main oscillator is configured and started. PLL
* parameters m and p are based on function parameters. The PLL is configured,
* started and selected as the main clock. AHB clock divider is set to 1.
*
* \param [in] crystal is the frequency of the crystal resonator connected to
* the LPC1114 chip.
* \param [in] frequency is the desired target frequency after enabling the PLL
*
* \return real frequency that was set
*//*-------------------------------------------------------------------------*/
static uint32_t pll_start(uint32_t crystal, uint32_t frequency)
{
uint32_t m, p = 0, fcco;
flash_access_time(frequency); // configure flash access time first
// SYSOSCCTRL_FREQRANGE should be 0 for crystals in range 1 - 20MHz
// SYSOSCCTRL_FREQRANGE should be 1 for crystals in range 15 - 25MHz
if (crystal < 17500000) // divide the ranges on 17.5MHz then
LPC_SYSCON->SYSOSCCTRL = 0; // "lower speed" crystals
else
LPC_SYSCON->SYSOSCCTRL = SYSOSCCTRL_FREQRANGE; // "higher speed" crystals
LPC_SYSCON->PDRUNCFG &= ~PDRUNCFG_SYSOSC_PD; // power-up main oscillator
LPC_SYSCON->SYSPLLCLKSEL = SYSPLLCLKSEL_SEL_IRC; // select main oscillator as the input clock for PLL
LPC_SYSCON->SYSPLLCLKUEN = 0; // confirm the change of PLL input clock by toggling the...
LPC_SYSCON->SYSPLLCLKUEN = SYSPLLUEN_ENA; // ...ENA bit in LPC_SYSCON->SYSPLLCLKUEN register
// calculate PLL parameters
m = frequency / crystal; // M is the PLL multiplier
fcco = m * crystal * 2; // FCCO is the internal PLL frequency
frequency = crystal * m;
while (fcco < 156000000)
{
fcco *= 2;
p++; // find P which gives FCCO in the allowed range (over 156MHz)
}
LPC_SYSCON->SYSPLLCTRL = ((m - 1) << SYSPLLCTRL_MSEL_bit) | (p << SYSPLLCTRL_PSEL_bit); // configure PLL
LPC_SYSCON->PDRUNCFG &= ~PDRUNCFG_SYSPLL_PD; // power-up PLL
while (!(LPC_SYSCON->SYSPLLSTAT & SYSPLLSTAT_LOCK)); // wait for PLL lock
LPC_SYSCON->MAINCLKSEL = MAINCLKSEL_SEL_PLLOUT; // select PLL output as the main clock
LPC_SYSCON->MAINCLKUEN = 0; // confirm the change of main clock by toggling the...
LPC_SYSCON->MAINCLKUEN = MAINCLKUEN_ENA; // ...ENA bit in LPC_SYSCON->MAINCLKUEN register
LPC_SYSCON->SYSAHBCLKDIV = 1; // set AHB clock divider to 1
return frequency;
}
/*------------------------------------------------------------------------*//**
* \brief Initializes system.
* \details Enables clock for IO configuration block.
*//*-------------------------------------------------------------------------*/
static void system_init(void)
{
LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_IOCON; // enable clock for IO configuration block
}
/*
+=============================================================================+
| ISRs
+=============================================================================+
*/
/******************************************************************************
* END OF FILE
******************************************************************************/