1 |
580 |
jeremybenn |
/* ----------------------------------------------------------------------------
|
2 |
|
|
* ATMEL Microcontroller Software Support
|
3 |
|
|
* ----------------------------------------------------------------------------
|
4 |
|
|
* Copyright (c) 2008, Atmel Corporation
|
5 |
|
|
*
|
6 |
|
|
* All rights reserved.
|
7 |
|
|
*
|
8 |
|
|
* Redistribution and use in source and binary forms, with or without
|
9 |
|
|
* modification, are permitted provided that the following conditions are met:
|
10 |
|
|
*
|
11 |
|
|
* - Redistributions of source code must retain the above copyright notice,
|
12 |
|
|
* this list of conditions and the disclaimer below.
|
13 |
|
|
*
|
14 |
|
|
* Atmel's name may not be used to endorse or promote products derived from
|
15 |
|
|
* this software without specific prior written permission.
|
16 |
|
|
*
|
17 |
|
|
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
18 |
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
19 |
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
20 |
|
|
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
21 |
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 |
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
23 |
|
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
24 |
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
25 |
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
26 |
|
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27 |
|
|
* ----------------------------------------------------------------------------
|
28 |
|
|
*/
|
29 |
|
|
|
30 |
|
|
#if defined(at91cap9)
|
31 |
|
|
//------------------------------------------------------------------------------
|
32 |
|
|
// Headers
|
33 |
|
|
//------------------------------------------------------------------------------
|
34 |
|
|
|
35 |
|
|
#include "slck.h"
|
36 |
|
|
#include <utility/assert.h>
|
37 |
|
|
#include <utility/trace.h>
|
38 |
|
|
#include <utility/util.h>
|
39 |
|
|
|
40 |
|
|
//------------------------------------------------------------------------------
|
41 |
|
|
// Local definitions
|
42 |
|
|
//------------------------------------------------------------------------------
|
43 |
|
|
|
44 |
|
|
/// Start Up Time Slow Clock 32K Oscillator // see DC characteritics in Datasheet
|
45 |
|
|
#define T_ST_SLCK_32K_IN_MS 1200
|
46 |
|
|
|
47 |
|
|
/// Start Up Time Slow Clock RC Oscillator // see DC characteritics in Datasheet
|
48 |
|
|
#define T_ST_SLCK_RC_IN_US 75
|
49 |
|
|
|
50 |
|
|
#define FREQ_SLCK_32K 32768 // see DC characteritics in Datasheet
|
51 |
|
|
#define MIN_FREQ_SLCK_RC 20000 // see DC characteritics in Datasheet
|
52 |
|
|
|
53 |
|
|
#define TIME_5_CYCLES_32K_IN_US ((2 * 5 * 1000000) / FREQ_SLCK_32K)
|
54 |
|
|
#define TIME_5_CYCLES_RC_IN_US ((2 * 5 * 1000000) / MIN_FREQ_SLCK_RC)
|
55 |
|
|
|
56 |
|
|
//------------------------------------------------------------------------------
|
57 |
|
|
// Local functions
|
58 |
|
|
//------------------------------------------------------------------------------
|
59 |
|
|
|
60 |
|
|
//------------------------------------------------------------------------------
|
61 |
|
|
/// Wait time in ms
|
62 |
|
|
//------------------------------------------------------------------------------
|
63 |
|
|
// not precise, depends on the compiler and on the options
|
64 |
|
|
static void WaitTimeInMs(unsigned int pck, unsigned int time_ms)
|
65 |
|
|
{
|
66 |
|
|
register unsigned int i = 0;
|
67 |
|
|
i = (pck / 1000) * time_ms;
|
68 |
|
|
i = i / 4;
|
69 |
|
|
while(i--);
|
70 |
|
|
}
|
71 |
|
|
|
72 |
|
|
//------------------------------------------------------------------------------
|
73 |
|
|
/// Wait time in us
|
74 |
|
|
//------------------------------------------------------------------------------
|
75 |
|
|
// not precise, depends on the compiler and on the options
|
76 |
|
|
static void WaitTimeInUs(unsigned int pck, unsigned int time_us)
|
77 |
|
|
{
|
78 |
|
|
volatile unsigned int i = 0;
|
79 |
|
|
i = (pck / 1000000) * time_us;
|
80 |
|
|
i = i / 4;
|
81 |
|
|
while(i--);
|
82 |
|
|
}
|
83 |
|
|
|
84 |
|
|
//------------------------------------------------------------------------------
|
85 |
|
|
// Global functions
|
86 |
|
|
//------------------------------------------------------------------------------
|
87 |
|
|
|
88 |
|
|
//------------------------------------------------------------------------------
|
89 |
|
|
/// Return 1 if the slow clock is 32k
|
90 |
|
|
//------------------------------------------------------------------------------
|
91 |
|
|
unsigned char SLCK_Is32k(void)
|
92 |
|
|
{
|
93 |
|
|
return ((*AT91C_SYS_SLCKSEL & AT91C_SLCKSEL_OSCSEL) != 0);
|
94 |
|
|
}
|
95 |
|
|
|
96 |
|
|
//------------------------------------------------------------------------------
|
97 |
|
|
/// Configure the 32kHz oscillator for the slow clock
|
98 |
|
|
//------------------------------------------------------------------------------
|
99 |
|
|
void SLCK_RCto32k(void)
|
100 |
|
|
{
|
101 |
|
|
// Check that the master clock has a different source than slow clock. If no,
|
102 |
|
|
if( (AT91C_BASE_PMC->PMC_MCKR & AT91C_PMC_CSS) == 0)
|
103 |
|
|
{
|
104 |
|
|
TRACE_WARNING("The master clock use the slow clock. " \
|
105 |
|
|
"Not possible to change Slow clock\n\r");
|
106 |
|
|
return;
|
107 |
|
|
}
|
108 |
|
|
|
109 |
|
|
// Check that the slow clock source is RC
|
110 |
|
|
if( SLCK_Is32k() )
|
111 |
|
|
{
|
112 |
|
|
TRACE_WARNING("The slow clock is already the external 32.768kHz crystal\n\r");
|
113 |
|
|
return;
|
114 |
|
|
}
|
115 |
|
|
|
116 |
|
|
// Enable the 32,768 Hz oscillator by setting the bit OSC32EN to 1.
|
117 |
|
|
*AT91C_SYS_SLCKSEL |= AT91C_SLCKSEL_OSC32EN;
|
118 |
|
|
|
119 |
|
|
// Wait 32,768 Hz Startup Time for clock stabilization (software loop).
|
120 |
|
|
WaitTimeInMs(BOARD_MCK*2, T_ST_SLCK_32K_IN_MS);
|
121 |
|
|
|
122 |
|
|
// Switch from internal RC to 32,768 Hz oscillator by setting the bit OSCSEL to 1.
|
123 |
|
|
*AT91C_SYS_SLCKSEL |= AT91C_SLCKSEL_OSCSEL;
|
124 |
|
|
|
125 |
|
|
// Wait 5 slow clock cycles for internal resynchronization.
|
126 |
|
|
WaitTimeInUs(BOARD_MCK*2, TIME_5_CYCLES_32K_IN_US);
|
127 |
|
|
|
128 |
|
|
// Disable the RC oscillator by setting the bit RCEN to 0.
|
129 |
|
|
*AT91C_SYS_SLCKSEL &= (0xFFFFFFFF ^ AT91C_SLCKSEL_RCEN);
|
130 |
|
|
|
131 |
|
|
TRACE_INFO("The slow clock is now the external 32.768kHz crystal\n\r");
|
132 |
|
|
}
|
133 |
|
|
|
134 |
|
|
|
135 |
|
|
//------------------------------------------------------------------------------
|
136 |
|
|
/// Configure the RC oscillator for the slow clock
|
137 |
|
|
//------------------------------------------------------------------------------
|
138 |
|
|
void SLCK_32ktoRC(void)
|
139 |
|
|
{
|
140 |
|
|
// Check that the master clock has a different source than slow clock.
|
141 |
|
|
if( (AT91C_BASE_PMC->PMC_MCKR & AT91C_PMC_CSS) == 0)
|
142 |
|
|
{
|
143 |
|
|
TRACE_WARNING("The master clock use the slow clock. " \
|
144 |
|
|
"Not possible to change Slow clock\n\r");
|
145 |
|
|
return;
|
146 |
|
|
}
|
147 |
|
|
|
148 |
|
|
// Check that the slow clock source is RC
|
149 |
|
|
if( !SLCK_Is32k() )
|
150 |
|
|
{
|
151 |
|
|
TRACE_WARNING("The slow clock is already the internal RC oscillator\n\r");
|
152 |
|
|
return;
|
153 |
|
|
}
|
154 |
|
|
|
155 |
|
|
// Enable the internal RC oscillator by setting the bit RCEN to 1
|
156 |
|
|
*AT91C_SYS_SLCKSEL |= AT91C_SLCKSEL_RCEN;
|
157 |
|
|
|
158 |
|
|
// Wait internal RC Startup Time for clock stabilization (software loop).
|
159 |
|
|
WaitTimeInUs(BOARD_MCK*2, T_ST_SLCK_RC_IN_US);
|
160 |
|
|
|
161 |
|
|
// Switch from 32768 Hz oscillator to internal RC by setting the bit OSCSEL to 0.
|
162 |
|
|
*AT91C_SYS_SLCKSEL &= (0xFFFFFFFF ^ AT91C_SLCKSEL_OSCSEL);
|
163 |
|
|
|
164 |
|
|
// Wait 5 slow clock cycles for internal resynchronization.
|
165 |
|
|
WaitTimeInUs(BOARD_MCK*2, TIME_5_CYCLES_RC_IN_US);
|
166 |
|
|
|
167 |
|
|
// Disable the 32768 Hz oscillator by setting the bit OSC32EN to 0.
|
168 |
|
|
*AT91C_SYS_SLCKSEL &= (0xFFFFFFFF ^ AT91C_SLCKSEL_OSC32EN);
|
169 |
|
|
|
170 |
|
|
TRACE_INFO("The slow clock is now the internal RC oscillator\n\r");
|
171 |
|
|
}
|
172 |
|
|
|
173 |
|
|
//------------------------------------------------------------------------------
|
174 |
|
|
/// by pass the 32kHz oscillator
|
175 |
|
|
//------------------------------------------------------------------------------
|
176 |
|
|
void SLCK_bypass32Kosc(void)
|
177 |
|
|
{
|
178 |
|
|
// Enable the bypass path OSC32BYP bit set to 1
|
179 |
|
|
*AT91C_SYS_SLCKSEL |= AT91C_SLCKSEL_OSC32BYP;
|
180 |
|
|
|
181 |
|
|
// Disable the 32,768 Hz oscillator by setting the bit OSC32EN to 0
|
182 |
|
|
*AT91C_SYS_SLCKSEL &= (0xFFFFFFFF ^ AT91C_SLCKSEL_OSC32EN);
|
183 |
|
|
}
|
184 |
|
|
|
185 |
|
|
//------------------------------------------------------------------------------
|
186 |
|
|
/// set Slow Clock Mode
|
187 |
|
|
//------------------------------------------------------------------------------
|
188 |
|
|
#define TIMEOUT 10000000
|
189 |
|
|
void SLCK_UtilSetSlowClockMode(unsigned int timeInSlowClockMode)
|
190 |
|
|
{
|
191 |
|
|
unsigned int oldPll;
|
192 |
|
|
unsigned int oldMck;
|
193 |
|
|
unsigned int timeout = 0;
|
194 |
|
|
|
195 |
|
|
// Save previous values for PLL A and Master Clock configuration
|
196 |
|
|
oldPll = AT91C_BASE_CKGR->CKGR_PLLAR;
|
197 |
|
|
oldMck = AT91C_BASE_PMC->PMC_MCKR;
|
198 |
|
|
|
199 |
|
|
// Slow clock is selected for Master Clock
|
200 |
|
|
// 32kKz / 64 = 500Hz
|
201 |
|
|
// PCK = 500Hz, MCK = 250 MHz
|
202 |
|
|
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_SLOW_CLK | AT91C_PMC_PRES_CLK_64 | AT91C_PMC_MDIV_2;
|
203 |
|
|
timeout = 0;
|
204 |
|
|
while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) && timeout++ < TIMEOUT);
|
205 |
|
|
|
206 |
|
|
// Stop PLL A
|
207 |
|
|
// MULA: PLL A Multiplier 0 = The PLL A is deactivated.
|
208 |
|
|
AT91C_BASE_CKGR->CKGR_PLLAR = 0x00003f00;
|
209 |
|
|
|
210 |
|
|
// Stop Main Oscillator
|
211 |
|
|
AT91C_BASE_CKGR->CKGR_MOR = AT91C_BASE_CKGR->CKGR_MOR & (~AT91C_CKGR_MOSCEN);
|
212 |
|
|
|
213 |
|
|
// Wait a while. The clock is at 500Hz...
|
214 |
|
|
while( timeInSlowClockMode-- );
|
215 |
|
|
// End !
|
216 |
|
|
|
217 |
|
|
// Restart Main Oscillator
|
218 |
|
|
AT91C_BASE_CKGR->CKGR_MOR = AT91C_BASE_CKGR->CKGR_MOR | (AT91C_CKGR_OSCOUNT & (0x32<<8) );
|
219 |
|
|
AT91C_BASE_CKGR->CKGR_MOR = AT91C_BASE_CKGR->CKGR_MOR | (AT91C_CKGR_MOSCEN);
|
220 |
|
|
|
221 |
|
|
// Restart PLL A
|
222 |
|
|
AT91C_BASE_CKGR->CKGR_PLLAR = oldPll;
|
223 |
|
|
timeout = 0;
|
224 |
|
|
while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKA) && timeout++ < TIMEOUT);
|
225 |
|
|
|
226 |
|
|
// Selection of Master Clock MCK (so Processor Clock PCK)
|
227 |
|
|
AT91C_BASE_PMC->PMC_MCKR = oldMck;
|
228 |
|
|
timeout = 0;
|
229 |
|
|
while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) && timeout++ < TIMEOUT);
|
230 |
|
|
|
231 |
|
|
// Reconfigure DBGU
|
232 |
|
|
TRACE_CONFIGURE(DBGU_STANDARD, 115200, BOARD_MCK);
|
233 |
|
|
}
|
234 |
|
|
|
235 |
|
|
//------------------------------------------------------------------------------
|
236 |
|
|
/// get the slow clock frequency
|
237 |
|
|
//------------------------------------------------------------------------------
|
238 |
|
|
unsigned int SLCK_UtilGetFreq(void)
|
239 |
|
|
{
|
240 |
|
|
unsigned int freq = 0;
|
241 |
|
|
|
242 |
|
|
SLCK_UtilSetSlowClockMode(0);
|
243 |
|
|
|
244 |
|
|
if(AT91C_BASE_PMC->PMC_MCFR & (1<<16)) {
|
245 |
|
|
freq = BOARD_MAINOSC / (AT91C_BASE_PMC->PMC_MCFR & 0x0000FFFF);
|
246 |
|
|
freq *= 16;
|
247 |
|
|
}
|
248 |
|
|
return freq;
|
249 |
|
|
}
|
250 |
|
|
|
251 |
|
|
#endif //#if defined(at91cap9)
|