1 /******************************************************************************************************************************************
2 * 文件名称: system_SWM341.c
3 * 功能说明: SWM341单片机的时钟设置
4 * 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1
5 * 注意事项:
6 * 版本日期: V1.1.0      2017年10月25日
7 * 升级记录:
8 *
9 *
10 *******************************************************************************************************************************************
11 * @attention
12 *
13 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION
14 * REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE
15 * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
16 * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN-
17 * -ECTION WITH THEIR PRODUCTS.
18 *
19 * COPYRIGHT 2012 Synwit Technology
20 *******************************************************************************************************************************************/
21 #include <stdint.h>
22 #include "SWM341.h"
23 
24 
25 /******************************************************************************************************************************************
26  * 系统时钟设定
27  *****************************************************************************************************************************************/
28 #define SYS_CLK_20MHz       0       //0 内部高频20MHz  RC振荡器
29 #define SYS_CLK_2M5Hz       1       //1 内部高频2.5MHz RC振荡器
30 #define SYS_CLK_40MHz       2       //2 内部高频40MHz  RC振荡器
31 #define SYS_CLK_5MHz        3       //3 内部高频 5MHz  RC振荡器
32 #define SYS_CLK_XTAL        4       //4 外部晶体振荡器(4-32MHz)
33 #define SYS_CLK_XTAL_DIV8   5       //5 外部晶体振荡器(4-32MHz) 8分频
34 #define SYS_CLK_PLL         6       //6 锁相环输出
35 #define SYS_CLK_PLL_DIV8    7       //7 锁相环输出 8分频
36 #define SYS_CLK_32KHz       8       //8 内部低频32KHz RC  振荡器
37 #define SYS_CLK_XTAL_32K    9       //9 外部低频32KHz 晶体振荡器
38 
39 #define SYS_CLK   SYS_CLK_PLL
40 
41 
42 #define __HSI       (20000000UL)        //高速内部时钟
43 #define __LSI       (   32000UL)        //低速内部时钟
44 #define __HSE       (12000000UL)        //高速外部时钟
45 #define __LSE       (   32768UL)        //低速外部时钟
46 
47 
48 /********************************** PLL 设定 **********************************************
49  * VCO输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV
50  * PLL输出频率 = PLL输入时钟 / INDIV * 4 * FBDIV / OUTDIV = VCO输出频率 / OUTDIV
51  * 注意:VCO输出频率需要在 [600MHz, 1400MHz] 之间
52  *****************************************************************************************/
53 #define SYS_PLL_SRC     SYS_CLK_XTAL    //可取值SYS_CLK_20MHz、SYS_CLK_XTAL
54 
55 #define PLL_IN_DIV      3
56 
57 #define PLL_FB_DIV      75
58 
59 
60 #define PLL_OUT_DIV8    0
61 #define PLL_OUT_DIV4    1
62 #define PLL_OUT_DIV2    2
63 
64 #define PLL_OUT_DIV     PLL_OUT_DIV8
65 
66 
67 
68 uint32_t SystemCoreClock  = __HSI;                  //System Clock Frequency (Core Clock)
69 uint32_t CyclesPerUs      = (__HSI / 1000000);      //Cycles per micro second
70 
71 
72 /******************************************************************************************************************************************
73 * 函数名称:
74 * 功能说明: This function is used to update the variable SystemCoreClock and must be called whenever the core clock is changed
75 * 输    入:
76 * 输    出:
77 * 注意事项:
78 ******************************************************************************************************************************************/
SystemCoreClockUpdate(void)79 void SystemCoreClockUpdate(void)
80 {
81     if(SYS->CLKSEL & SYS_CLKSEL_SYS_Msk)            //SYS  <= HRC
82     {
83         if(SYS->HRCCR & SYS_HRCCR_DBL_Msk)              //HRC = 40MHz
84         {
85             SystemCoreClock = __HSI*2;
86         }
87         else                                            //HRC = 20MHz
88         {
89             SystemCoreClock = __HSI;
90         }
91     }
92     else                                            //SYS  <= CLK
93     {
94         switch((SYS->CLKSEL & SYS_CLKSEL_CLK_Msk) >> SYS_CLKSEL_CLK_Pos)
95         {
96         case 0:
97             SystemCoreClock = __LSI;
98             break;
99 
100         case 1:
101             if(SYS->PLLCR & SYS_PLLCR_INSEL_Msk)            //PLL_IN <= HRC
102             {
103                 SystemCoreClock = __HSI;
104             }
105             else                                            //PLL_IN <= XTAL
106             {
107                 SystemCoreClock = __HSE;
108             }
109 
110             SystemCoreClock = SystemCoreClock / PLL_IN_DIV * PLL_FB_DIV * 4 / (2 << (2 - PLL_OUT_DIV));
111             break;
112 
113         case 2:
114             SystemCoreClock = __LSE;
115             break;
116 
117         case 3:
118             SystemCoreClock = __HSE;
119             break;
120 
121         case 4:
122             SystemCoreClock = __HSI;
123             if(SYS->HRCCR & SYS_HRCCR_DBL_Msk)  SystemCoreClock *= 2;
124             break;
125         }
126 
127         if(SYS->CLKSEL & SYS_CLKSEL_CLK_DIVx_Msk)  SystemCoreClock /= 8;
128     }
129 
130     CyclesPerUs = SystemCoreClock / 1000000;
131 }
132 
133 /******************************************************************************************************************************************
134 * 函数名称:
135 * 功能说明: The necessary initializaiton of systerm
136 * 输    入:
137 * 输    出:
138 * 注意事项:
139 ******************************************************************************************************************************************/
SystemInit(void)140 void SystemInit(void)
141 {
142     SYS->CLKEN0 |= (1 << SYS_CLKEN0_ANAC_Pos);
143 
144     Flash_Param_at_xMHz(150);
145 
146     switch(SYS_CLK)
147     {
148         case SYS_CLK_20MHz:
149             switchTo20MHz();
150             break;
151 
152         case SYS_CLK_2M5Hz:
153             switchTo2M5Hz();
154             break;
155 
156         case SYS_CLK_40MHz:
157             switchTo40MHz();
158             break;
159 
160         case SYS_CLK_5MHz:
161             switchTo5MHz();
162             break;
163 
164         case SYS_CLK_XTAL:
165             switchToXTAL(0);
166             break;
167 
168         case SYS_CLK_XTAL_DIV8:
169             switchToXTAL(1);
170             break;
171 
172         case SYS_CLK_PLL:
173             switchToPLL(0);
174             break;
175 
176         case SYS_CLK_PLL_DIV8:
177             switchToPLL(1);
178             break;
179 
180         case SYS_CLK_32KHz:
181             switchTo32KHz();
182             break;
183 
184         case SYS_CLK_XTAL_32K:
185             switchToXTAL_32K();
186             break;
187     }
188 
189     SystemCoreClockUpdate();
190 
191     if(SystemCoreClock > 120000000)
192     {
193         Flash_Param_at_xMHz(150);
194     }
195     else if(SystemCoreClock > 80000000)
196     {
197         Flash_Param_at_xMHz(120);
198     }
199     else if(SystemCoreClock > 40000000)
200     {
201         Flash_Param_at_xMHz(80);
202     }
203     else if(SystemCoreClock > 30000000)
204     {
205         Flash_Param_at_xMHz(40);
206     }
207     else
208     {
209         Flash_Param_at_xMHz(30);
210     }
211 
212     PORTM->PULLD &= ~(1 << PIN1);
213     PORTM->PULLU &= ~((1 << PIN2) | (1 << PIN3));
214 
215     SYS->USBPHYCR &= ~SYS_USBPHYCR_OPMODE_Msk;
216     SYS->USBPHYCR |= (1 << SYS_USBPHYCR_OPMODE_Pos);    //Non-Driving, DP Pull-Up disable
217 }
218 
219 
FPU_Enable(void)220 void FPU_Enable(void)
221 {
222 #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
223     SCB->CPACR |= (0xF << 20);
224 #endif
225 }
226 
227 
delay_3ms(void)228 static void delay_3ms(void)
229 {
230     uint32_t i;
231 
232     if(((SYS->CLKSEL & SYS_CLKSEL_SYS_Msk) == 0) &&
233        ((((SYS->CLKSEL & SYS_CLKSEL_CLK_Msk) >> SYS_CLKSEL_CLK_Pos) == 0) ||   //LSI 32KHz
234         (((SYS->CLKSEL & SYS_CLKSEL_CLK_Msk) >> SYS_CLKSEL_CLK_Pos) == 2)))    //LSE 32KHz
235     {
236         for(i = 0; i < 20; i++) __NOP();
237     }
238     else
239     {
240         for(i = 0; i < 20000; i++) __NOP();
241     }
242 }
243 
244 
switchTo20MHz(void)245 void switchTo20MHz(void)
246 {
247     SYS->HRCCR = (1 << SYS_HRCCR_ON_Pos) |
248                  (0 << SYS_HRCCR_DBL_Pos);          //HRC = 20Hz
249 
250     delay_3ms();
251 
252     SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos);       //SYS <= HRC
253 }
254 
switchTo2M5Hz(void)255 void switchTo2M5Hz(void)
256 {
257     switchTo20MHz();
258 
259     SYS->CLKDIVx_ON = 1;
260 
261     SYS->CLKSEL &= ~SYS_CLKSEL_CLK_Msk;
262     SYS->CLKSEL |= (4 << SYS_CLKSEL_CLK_Pos);       //CLK <= HRC
263 
264     SYS->CLKSEL |= (1 << SYS_CLKSEL_CLK_DIVx_Pos);
265 
266     delay_3ms();
267 
268     SYS->CLKSEL &=~(1 << SYS_CLKSEL_SYS_Pos);       //SYS <= HRC/8
269 }
270 
switchTo40MHz(void)271 void switchTo40MHz(void)
272 {
273     SYS->HRCCR = (1 << SYS_HRCCR_ON_Pos) |
274                  (1 << SYS_HRCCR_DBL_Pos);          //HRC = 40MHz
275 
276     delay_3ms();
277 
278     SYS->CLKSEL |= (1 << SYS_CLKSEL_SYS_Pos);       //SYS <= HRC
279 }
280 
switchTo5MHz(void)281 void switchTo5MHz(void)
282 {
283     switchTo40MHz();
284 
285     SYS->CLKDIVx_ON = 1;
286 
287     SYS->CLKSEL &= ~SYS_CLKSEL_CLK_Msk;
288     SYS->CLKSEL |= (4 << SYS_CLKSEL_CLK_Pos);       //CLK <= HRC
289 
290     SYS->CLKSEL |= (1 << SYS_CLKSEL_CLK_DIVx_Pos);
291 
292     delay_3ms();
293 
294     SYS->CLKSEL &=~(1 << SYS_CLKSEL_SYS_Pos);       //SYS <= HRC/8
295 }
296 
switchToXTAL(uint32_t div8)297 void switchToXTAL(uint32_t div8)
298 {
299     switchTo20MHz();
300 
301     PORT_Init(PORTA, PIN3, PORTA_PIN3_XTAL_IN,  0);
302     PORT_Init(PORTA, PIN4, PORTA_PIN4_XTAL_OUT, 0);
303     SYS->XTALCR |= (1 << SYS_XTALCR_ON_Pos) | (15 << SYS_XTALCR_DRV_Pos) | (1 << SYS_XTALCR_DET_Pos);
304 
305     delay_3ms();
306     delay_3ms();
307 
308     SYS->CLKDIVx_ON = 1;
309 
310     SYS->CLKSEL &= ~SYS_CLKSEL_CLK_Msk;
311     SYS->CLKSEL |= (3 << SYS_CLKSEL_CLK_Pos);       //CLK <= XTAL
312 
313     if(div8) SYS->CLKSEL |= (1 << SYS_CLKSEL_CLK_DIVx_Pos);
314     else     SYS->CLKSEL &=~(1 << SYS_CLKSEL_CLK_DIVx_Pos);
315 
316     SYS->CLKSEL &=~(1 << SYS_CLKSEL_SYS_Pos);       //SYS <= XTAL
317 }
318 
switchToPLL(uint32_t div8)319 void switchToPLL(uint32_t div8)
320 {
321     switchTo20MHz();
322 
323     PLLInit();
324 
325     SYS->CLKDIVx_ON = 1;
326 
327     SYS->CLKSEL &= ~SYS_CLKSEL_CLK_Msk;
328     SYS->CLKSEL |= (1 << SYS_CLKSEL_CLK_Pos);       //CLK <= PLL
329 
330     if(div8)  SYS->CLKSEL |= (1 << SYS_CLKSEL_CLK_DIVx_Pos);
331     else      SYS->CLKSEL &=~(1 << SYS_CLKSEL_CLK_DIVx_Pos);
332 
333     SYS->CLKSEL &=~(1 << SYS_CLKSEL_SYS_Pos);       //SYS <= PLL
334 }
335 
switchTo32KHz(void)336 void switchTo32KHz(void)
337 {
338     switchTo20MHz();
339 
340     SYS->LRCCR = (1 << SYS_LRCCR_ON_Pos);
341 
342     SYS->CLKDIVx_ON = 1;
343 
344     SYS->CLKSEL &= ~SYS_CLKSEL_CLK_Msk;
345     SYS->CLKSEL |= (0 << SYS_CLKSEL_CLK_Pos);       //CLK <= LRC
346 
347     SYS->CLKSEL &=~(1 << SYS_CLKSEL_CLK_DIVx_Pos);
348 
349     delay_3ms();
350 
351     SYS->CLKSEL &=~(1 << SYS_CLKSEL_SYS_Pos);       //SYS <= LRC
352 }
353 
switchToXTAL_32K(void)354 void switchToXTAL_32K(void)
355 {
356     uint32_t i;
357 
358     switchTo20MHz();
359 
360     SYS->XTALCR |= (1 << SYS_XTALCR_32KON_Pos) | (7 << SYS_XTALCR_32KDRV_Pos) | (1 << SYS_XTALCR_32KDET_Pos);
361     for(i = 0; i < 1000; i++) __NOP();
362 
363     SYS->CLKDIVx_ON = 1;
364 
365     SYS->CLKSEL &= ~SYS_CLKSEL_CLK_Msk;
366     SYS->CLKSEL |= (2 << SYS_CLKSEL_CLK_Pos);       //CLK <= XTAL_32K
367 
368     SYS->CLKSEL &=~(1 << SYS_CLKSEL_CLK_DIVx_Pos);
369 
370     delay_3ms();
371 
372     SYS->CLKSEL &=~(1 << SYS_CLKSEL_SYS_Pos);       //SYS <= XTAL_32K
373 }
374 
PLLInit(void)375 void PLLInit(void)
376 {
377     if(SYS_PLL_SRC == SYS_CLK_20MHz)
378     {
379         SYS->HRCCR = (1 << SYS_HRCCR_ON_Pos) |
380                      (0 << SYS_HRCCR_DBL_Pos);      //HRC = 20Hz
381 
382         delay_3ms();
383 
384         SYS->PLLCR |= (1 << SYS_PLLCR_INSEL_Pos);   //PLL_SRC <= HRC
385     }
386     else if(SYS_PLL_SRC == SYS_CLK_XTAL)
387     {
388         PORT_Init(PORTA, PIN3, PORTA_PIN3_XTAL_IN,  0);
389         PORT_Init(PORTA, PIN4, PORTA_PIN4_XTAL_OUT, 0);
390         SYS->XTALCR |= (1 << SYS_XTALCR_ON_Pos) | (15 << SYS_XTALCR_DRV_Pos) | (1 << SYS_XTALCR_DET_Pos);
391 
392         delay_3ms();
393         delay_3ms();
394 
395         SYS->PLLCR &= ~(1 << SYS_PLLCR_INSEL_Pos);  //PLL_SRC <= XTAL
396     }
397 
398     SYS->PLLDIV &= ~(SYS_PLLDIV_INDIV_Msk |
399                      SYS_PLLDIV_FBDIV_Msk |
400                      SYS_PLLDIV_OUTDIV_Msk);
401     SYS->PLLDIV |= (PLL_IN_DIV << SYS_PLLDIV_INDIV_Pos) |
402                    (PLL_FB_DIV << SYS_PLLDIV_FBDIV_Pos) |
403                    (PLL_OUT_DIV<< SYS_PLLDIV_OUTDIV_Pos);
404 
405     SYS->PLLCR &= ~(1 << SYS_PLLCR_OFF_Pos);
406 
407     while(SYS->PLLLOCK == 0);       //等待PLL锁定
408 
409     SYS->PLLCR |= (1 << SYS_PLLCR_OUTEN_Pos);
410 }
411