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