1 /******************************************************************************
2 *Copyright(C)2018, Huada Semiconductor Co.,Ltd All rights reserved.
3 *
4 * This software is owned and published by:
5 * Huada Semiconductor Co.,Ltd("HDSC").
6 *
7 * BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
8 * BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
9 *
10 * This software contains source code for use with HDSC
11 * components. This software is licensed by HDSC to be adapted only
12 * for use in systems utilizing HDSC components. HDSC shall not be
13 * responsible for misuse or illegal use of this software for devices not
14 * supported herein. HDSC is providing this software "AS IS" and will
15 * not be responsible for issues arising from incorrect user implementation
16 * of the software.
17 *
18 * Disclaimer:
19 * HDSC MAKES NO WARRANTY, EXPRESS OR IMPLIED, ARISING BY LAW OR OTHERWISE,
20 * REGARDING THE SOFTWARE (INCLUDING ANY ACOOMPANYING WRITTEN MATERIALS),
21 * ITS PERFORMANCE OR SUITABILITY FOR YOUR INTENDED USE, INCLUDING,
22 * WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, THE IMPLIED
23 * WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE OR USE, AND THE IMPLIED
24 * WARRANTY OF NONINFRINGEMENT.
25 * HDSC SHALL HAVE NO LIABILITY (WHETHER IN CONTRACT, WARRANTY, TORT,
26 * NEGLIGENCE OR OTHERWISE) FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT
27 * LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION,
28 * LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING FROM USE OR
29 * INABILITY TO USE THE SOFTWARE, INCLUDING, WITHOUT LIMITATION, ANY DIRECT,
30 * INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOSS OF DATA,
31 * SAVINGS OR PROFITS,
32 * EVEN IF Disclaimer HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
33 * YOU ASSUME ALL RESPONSIBILITIES FOR SELECTION OF THE SOFTWARE TO ACHIEVE YOUR
34 * INTENDED RESULTS, AND FOR THE INSTALLATION OF, USE OF, AND RESULTS OBTAINED
35 * FROM, THE SOFTWARE.
36 *
37 * This software may be replicated in part or whole for the licensed use,
38 * with the restriction that this Disclaimer and Copyright notice must be
39 * included with each copy of this software, whether used in part or whole,
40 * at all times.
41 */
42 
43 /** \file sysctrl.c
44  **
45  ** Common API of sysctrl.
46  ** @link SysctrlGroup Some description @endlink
47  **
48  **   - 2018-04-22 Lux
49  **
50  ******************************************************************************/
51 
52 /*******************************************************************************
53  * Include files
54  ******************************************************************************/
55 #include "hc32l196_sysctrl.h"
56 
57 /**
58  *******************************************************************************
59  ** \addtogroup SysctrlGroup
60  ******************************************************************************/
61 //@{
62 
63 /*******************************************************************************
64  * Local pre-processor symbols/macros ('#define')
65  ******************************************************************************/
66 #define CLK_TIMEOUT             (1000000u)
67 
68 #define IS_VALID_SRC(x)         (   ClkRCH == (x)||\
69                                     ClkXTH == (x)||\
70                                     ClkRCL == (x)||\
71                                     ClkXTL == (x) )
72 
73 
74 #define IS_VALID_FUNC(x)        (   ClkFuncWkupRCH == (x)||\
75                                     ClkFuncXTHEn == (x)||\
76                                     ClkFuncXTLEn == (x)||\
77                                     ClkFuncXTLAWSON == (x)||\
78                                     ClkFuncFaultEn == (x)||\
79                                     ClkFuncRtcLPWEn == (x)||\
80                                     ClkFuncLockUpEn == (x)||\
81                                     ClkFuncRstPinIOEn == (x)||\
82                                     ClkFuncSwdPinIOEn == (x) )
83 
84 #define RC_TRIM_BASE_ADDR           ((volatile uint16_t*) (0x00100C00ul))
85 #define RCH_CR_TRIM_24M_VAL         (*((volatile uint16_t*) (0x00100C00ul)))
86 #define RCH_CR_TRIM_22_12M_VAL      (*((volatile uint16_t*) (0x00100C02ul)))
87 #define RCH_CR_TRIM_16M_VAL         (*((volatile uint16_t*) (0x00100C04ul)))
88 #define RCH_CR_TRIM_8M_VAL          (*((volatile uint16_t*) (0x00100C06ul)))
89 #define RCH_CR_TRIM_4M_VAL          (*((volatile uint16_t*) (0x00100C08ul)))
90 
91 #define RCL_CR_TRIM_38400_VAL       (*((volatile uint16_t*) (0x00100C20ul)))
92 #define RCL_CR_TRIM_32768_VAL       (*((volatile uint16_t*) (0x00100C22ul)))
93 
94 /*******************************************************************************
95  * Global variable definitions (declared in header file with 'extern')
96  ******************************************************************************/
97 extern uint32_t SystemCoreClock;
98 /*******************************************************************************
99  * Local type definitions ('typedef')
100  ******************************************************************************/
101 
102 /*******************************************************************************
103  * Local variable definitions ('static')
104  ******************************************************************************/
105 
106 /*******************************************************************************
107  * Local function prototypes ('static')
108  ******************************************************************************/
109 
110 
111 /*******************************************************************************
112  * Function implementation - global ('extern') and local ('static')
113  ******************************************************************************/
114 
115 /**
116  *******************************************************************************
117  ** \brief SYSCTRL0\SYSCTRL1寄存器操作解锁
118  **
119  ** \retval None
120  ******************************************************************************/
_SysctrlUnlock(void)121 static void _SysctrlUnlock(void)
122 {
123     M0P_SYSCTRL->SYSCTRL2 = 0x5A5A;
124     M0P_SYSCTRL->SYSCTRL2 = 0xA5A5;
125 }
126 
127 /**
128  *******************************************************************************
129  ** \brief 系统时钟源使能
130  ** \param [in]  enSource   目标时钟源
131  ** \param [in]  bFlag      使能1-开/0-关
132  ** \retval      Ok         设定成功
133  **             其他        设定失败
134  ******************************************************************************/
Sysctrl_ClkSourceEnable(en_sysctrl_clk_source_t enSource,boolean_t bFlag)135 en_result_t Sysctrl_ClkSourceEnable(en_sysctrl_clk_source_t enSource, boolean_t bFlag)
136 {
137     en_result_t enRet = Ok;
138     uint32_t u32Temp;
139 
140     _SysctrlUnlock();
141     bFlag = !!bFlag;
142 
143     u32Temp = M0P_SYSCTRL->PERI_CLKEN0;
144     switch (enSource)
145     {
146         case SysctrlClkRCH:
147             M0P_SYSCTRL->SYSCTRL0_f.RCH_EN = bFlag;
148             while(bFlag && (1 != M0P_SYSCTRL->RCH_CR_f.STABLE))
149             {
150                 ;
151             }
152             break;
153 
154         case SysctrlClkXTH:
155             M0P_SYSCTRL->PERI_CLKEN0_f.GPIO = TRUE;
156             M0P_GPIO->PFADS |= 3u;
157             M0P_SYSCTRL->SYSCTRL0_f.XTH_EN = bFlag;
158             while(bFlag && (1 != M0P_SYSCTRL->XTH_CR_f.STABLE))
159             {
160                 ;
161             }
162             break;
163 
164         case SysctrlClkRCL:
165 
166             M0P_SYSCTRL->SYSCTRL0_f.RCL_EN = bFlag;
167             while(bFlag && (1 != M0P_SYSCTRL->RCL_CR_f.STABLE))
168             {
169                 ;
170             }
171             break;
172 
173         case SysctrlClkXTL:
174             M0P_SYSCTRL->PERI_CLKEN0_f.GPIO = TRUE;
175             M0P_GPIO->PCADS |= 0xC000;
176             M0P_SYSCTRL->SYSCTRL0_f.XTL_EN = bFlag;
177             while(bFlag && (1 != M0P_SYSCTRL->XTL_CR_f.STABLE))
178             {
179                 ;
180             }
181             break;
182 
183         case SysctrlClkPLL:
184             M0P_SYSCTRL->PERI_CLKEN0_f.ADC = TRUE;
185             M0P_BGR->CR_f.BGR_EN = TRUE;
186             delay10us(20);
187             M0P_SYSCTRL->SYSCTRL0_f.PLL_EN = bFlag;
188             while(bFlag && (1 != M0P_SYSCTRL->PLL_CR_f.STABLE))
189             {
190                 ;
191             }
192             break;
193 
194         default:
195             enRet = ErrorInvalidParameter;
196             break;
197     }
198     M0P_SYSCTRL->PERI_CLKEN0 = u32Temp;
199 
200     return enRet;
201 }
202 
203 /**
204  *******************************************************************************
205  ** \brief 外部高速晶振驱动配置
206  ** \param [in]  enFreq     外部高速晶振频率范围选择
207  ** \param [in]  enDriver   外部高速晶振驱动能力选择
208  ** \retval      Ok         设定成功
209  **             其他        设定失败
210  ******************************************************************************/
Sysctrl_XTHDriverCfg(en_sysctrl_xtal_driver_t enDriver)211 en_result_t Sysctrl_XTHDriverCfg(en_sysctrl_xtal_driver_t enDriver)
212 {
213     en_result_t enRet = Ok;
214 
215     M0P_SYSCTRL->XTH_CR_f.DRIVER   = enDriver;
216 
217     return enRet;
218 }
219 
220 /**
221  *******************************************************************************
222  ** \brief 外部低速晶振驱动配置
223  ** \param [in]  enFreq     外部低速晶振频率范围选择
224  ** \param [in]  enDriver   外部低速晶振驱动能力选择
225  ** \retval      Ok         设定成功
226  **             其他        设定失败
227  ******************************************************************************/
Sysctrl_XTLDriverCfg(en_sysctrl_xtl_amp_t enAmp,en_sysctrl_xtal_driver_t enDriver)228 en_result_t Sysctrl_XTLDriverCfg(en_sysctrl_xtl_amp_t enAmp, en_sysctrl_xtal_driver_t enDriver)
229 {
230     en_result_t enRet = Ok;
231 
232     M0P_SYSCTRL->XTL_CR_f.AMP_SEL = enAmp;
233     M0P_SYSCTRL->XTL_CR_f.DRIVER  = enDriver;
234 
235     return enRet;
236 }
237 
238 /**
239  *******************************************************************************
240  ** \brief 外部高速时钟稳定周期配置
241  ** \param [in]  enCycle     外部高速时钟稳定周期设置
242  ** \retval      Ok         设定成功
243  **             其他        设定失败
244  ******************************************************************************/
Sysctrl_SetXTHStableTime(en_sysctrl_xth_cycle_t enCycle)245 en_result_t Sysctrl_SetXTHStableTime(en_sysctrl_xth_cycle_t enCycle)
246 {
247     en_result_t enRet = Ok;
248     M0P_SYSCTRL->XTH_CR_f.STARTUP = enCycle;
249     return enRet;
250 }
251 
252 /**
253  *******************************************************************************
254  ** \brief 内部低速时钟稳定周期配置
255  ** \param [in]  enCycle     内部低速时钟稳定周期设置
256  ** \retval      Ok         设定成功
257  **             其他        设定失败
258  ******************************************************************************/
Sysctrl_SetRCLStableTime(en_sysctrl_rcl_cycle_t enCycle)259 en_result_t Sysctrl_SetRCLStableTime(en_sysctrl_rcl_cycle_t enCycle)
260 {
261     en_result_t enRet = Ok;
262     M0P_SYSCTRL->RCL_CR_f.STARTUP = enCycle;
263     return enRet;
264 }
265 
266 /**
267  *******************************************************************************
268  ** \brief 外部低速时钟稳定周期配置
269  ** \param [in]  enCycle     外部低速时钟稳定周期设置
270  ** \retval      Ok         设定成功
271  **             其他        设定失败
272  ******************************************************************************/
Sysctrl_SetXTLStableTime(en_sysctrl_xtl_cycle_t enCycle)273 en_result_t Sysctrl_SetXTLStableTime(en_sysctrl_xtl_cycle_t enCycle)
274 {
275     en_result_t enRet = Ok;
276     M0P_SYSCTRL->XTL_CR_f.STARTUP = enCycle;
277     return enRet;
278 }
279 
280 /**
281  *******************************************************************************
282  ** \brief PLL稳定周期配置
283  ** \param [in]  enCycle    PLL稳定周期设置
284  ** \retval      Ok         设定成功
285  **             其他        设定失败
286  ******************************************************************************/
Sysctrl_SetPLLStableTime(en_sysctrl_pll_cycle_t enCycle)287 en_result_t Sysctrl_SetPLLStableTime(en_sysctrl_pll_cycle_t enCycle)
288 {
289     en_result_t enRet = Ok;
290     M0P_SYSCTRL->PLL_CR_f.STARTUP = enCycle;
291     return enRet;
292 }
293 
294 /**
295  *******************************************************************************
296  ** \brief 时钟源切换,该函数执行后会开启新时钟源
297  ** \note  选择时钟源之前,需根据需要配置目标时钟源的频率/驱动参数/使能时钟源等
298  ** \param [in]  enSource   新时钟源
299  **
300  ** \retval      Ok         设定成功
301  **              其他       设定失败
302  ******************************************************************************/
Sysctrl_SysClkSwitch(en_sysctrl_clk_source_t enSource)303 en_result_t Sysctrl_SysClkSwitch(en_sysctrl_clk_source_t enSource)
304 {
305     en_result_t enRet = Ok;
306 
307     en_sysctrl_clk_source_t ClkNew = enSource;
308 
309     _SysctrlUnlock();
310     M0P_SYSCTRL->SYSCTRL0_f.CLKSW = ClkNew;
311 
312     //更新Core时钟(HCLK)
313     SystemCoreClockUpdate();
314 
315     return enRet;
316 }
317 
318 /**
319  *******************************************************************************
320  ** \brief   获得系统时钟(HCLK)频率值
321  ** \retval  uint32_t         HCLK频率值
322  **
323  ******************************************************************************/
Sysctrl_GetHClkFreq(void)324 uint32_t Sysctrl_GetHClkFreq(void)
325 {
326     uint32_t u32Val = 0;
327     const uint32_t u32hcr_tbl[] = { 4000000, 8000000, 16000000, 22120000, 24000000};
328     const uint16_t u32lcr_tbl[] = { 32768, 38400};
329     en_sysctrl_clk_source_t enSrc;
330     uint16_t u16Trim[5] = {0};
331     u16Trim[4] = RCH_CR_TRIM_24M_VAL;
332     u16Trim[3] = RCH_CR_TRIM_22_12M_VAL;
333     u16Trim[2] = RCH_CR_TRIM_16M_VAL;
334     u16Trim[1] = RCH_CR_TRIM_8M_VAL;
335     u16Trim[0] = RCL_CR_TRIM_38400_VAL;
336 
337     //获取当前系统时钟
338     enSrc = (en_sysctrl_clk_source_t)(M0P_SYSCTRL->SYSCTRL0_f.CLKSW);
339 
340     switch (enSrc)
341     {
342         case SysctrlClkRCH:
343             {
344 
345                 if((M0P_SYSCTRL->RCH_CR_f.TRIM) == (u16Trim[4]))
346                 {
347                     u32Val = u32hcr_tbl[4];
348                 }
349                 else if((M0P_SYSCTRL->RCH_CR_f.TRIM) == (u16Trim[3]))
350                 {
351                     u32Val = u32hcr_tbl[3];
352                 }
353                 else if((M0P_SYSCTRL->RCH_CR_f.TRIM) == (u16Trim[2]))
354                 {
355                     u32Val = u32hcr_tbl[2];
356                 }
357                 else if((M0P_SYSCTRL->RCH_CR_f.TRIM) == (u16Trim[1]))
358                 {
359                     u32Val = u32hcr_tbl[1];
360                 }
361                 else
362                 {
363                     u32Val = u32hcr_tbl[0];
364                 }
365             }
366             break;
367         case SysctrlClkXTH:
368             u32Val = SYSTEM_XTH;
369             break;
370         case SysctrlClkRCL:
371             {
372                 if(u16Trim[0] == (M0P_SYSCTRL->RCL_CR_f.TRIM))
373                 {
374                     u32Val = u32lcr_tbl[1];
375                 }
376                 else
377                 {
378                     u32Val = u32lcr_tbl[0];
379                 }
380             }
381             break;
382         case SysctrlClkXTL:
383             u32Val = SYSTEM_XTL;
384             break;
385         case SysctrlClkPLL:
386             {
387                 if (SysctrlPllRch == M0P_SYSCTRL->PLL_CR_f.REFSEL)
388                 {
389                     if(u16Trim[4] == M0P_SYSCTRL->RCH_CR_f.TRIM)
390                     {
391                         u32Val = u32hcr_tbl[4];
392                     }
393                     else if(u16Trim[3] == M0P_SYSCTRL->RCH_CR_f.TRIM)
394                     {
395                         u32Val = u32hcr_tbl[3];
396                     }
397                     else if(u16Trim[2] == M0P_SYSCTRL->RCH_CR_f.TRIM)
398                     {
399                         u32Val = u32hcr_tbl[2];
400                     }
401                     else if(u16Trim[1] == M0P_SYSCTRL->RCH_CR_f.TRIM)
402                     {
403                         u32Val = u32hcr_tbl[1];
404                     }
405                     else
406                     {
407                         u32Val = u32hcr_tbl[0];
408                     }
409                 }
410                 else
411                 {
412                     u32Val = SYSTEM_XTH;
413                 }
414 
415                 u32Val = (u32Val * M0P_SYSCTRL->PLL_CR_f.DIVN);
416             }
417             break;
418         default:
419             u32Val = 0u;
420             break;
421     }
422 
423     u32Val = (u32Val >> M0P_SYSCTRL->SYSCTRL0_f.HCLK_PRS);
424 
425     return u32Val;
426 }
427 
428 /**
429  *******************************************************************************
430  ** \brief 获得外设时钟(PCLK)频率值
431  ** \retval uint32_t   PCLK频率值(Hz)
432  **
433  ******************************************************************************/
Sysctrl_GetPClkFreq(void)434 uint32_t Sysctrl_GetPClkFreq(void)
435 {
436     uint32_t u32Val = 0;
437 
438     u32Val = Sysctrl_GetHClkFreq();
439     u32Val = (u32Val >> (M0P_SYSCTRL->SYSCTRL0_f.PCLK_PRS));
440 
441     return u32Val;
442 }
443 
444 
445 /**
446  *******************************************************************************
447  ** \brief 时钟初始化函数
448  ** \param [in]  pstcCfg    初始化配置参数
449  ** \retval      Ok         设定成功
450  **             其他        设定失败
451  ******************************************************************************/
Sysctrl_ClkInit(stc_sysctrl_clk_cfg_t * pstcCfg)452 en_result_t Sysctrl_ClkInit(stc_sysctrl_clk_cfg_t *pstcCfg)
453 {
454     en_result_t enRet = Ok;
455 
456     //系统时钟参数配置
457     switch(pstcCfg->enClkSrc)
458     {
459         case SysctrlClkRCH:
460 
461             break;
462         case SysctrlClkXTH:
463             Sysctrl_XTHDriverCfg(SysctrlXtalDriver3);
464             Sysctrl_SetXTHStableTime(SysctrlXthStableCycle16384);
465             break;
466         case SysctrlClkRCL:
467             Sysctrl_SetRCLStableTime(SysctrlRclStableCycle256);
468             break;
469         case SysctrlClkXTL:
470             Sysctrl_XTLDriverCfg(SysctrlXtlAmp3, SysctrlXtalDriver3);
471             Sysctrl_SetXTLStableTime(SysctrlXtlStableCycle16384);
472             break;
473         case SysctrlClkPLL:
474             Sysctrl_SetPLLStableTime(SysctrlPllStableCycle16384);
475             break;
476         default:
477             enRet = ErrorInvalidParameter;
478             break;
479     }
480 
481     //时钟源使能
482     Sysctrl_ClkSourceEnable(pstcCfg->enClkSrc, TRUE);
483 
484     //时钟源切换
485     Sysctrl_SysClkSwitch(pstcCfg->enClkSrc);
486 
487     //时钟分频设置
488     Sysctrl_SetHCLKDiv(pstcCfg->enHClkDiv);
489     Sysctrl_SetPCLKDiv(pstcCfg->enPClkDiv);
490 
491     return enRet;
492 }
493 
494 /**
495  *******************************************************************************
496  ** \brief 时钟去初始化函数
497  ** \param [in]
498  ** \retval      Ok         设定成功
499  **             其他        设定失败
500  ******************************************************************************/
Sysctrl_ClkDeInit(void)501 en_result_t Sysctrl_ClkDeInit(void)
502 {
503     en_result_t enRet = Ok;
504 
505     //配置RCH为内部4Hz
506     Sysctrl_SetRCHTrim(SysctrlRchFreq4MHz);
507 
508     //时钟源使能
509     Sysctrl_ClkSourceEnable(SysctrlClkRCH, TRUE);
510 
511     //时钟源切换
512     Sysctrl_SysClkSwitch(SysctrlClkRCH);
513 
514     //其它时钟源使能关闭
515     Sysctrl_ClkSourceEnable(SysctrlClkXTH, FALSE);
516     Sysctrl_ClkSourceEnable(SysctrlClkRCL, FALSE);
517     Sysctrl_ClkSourceEnable(SysctrlClkXTL, FALSE);
518     Sysctrl_ClkSourceEnable(SysctrlClkPLL, FALSE);
519 
520     //时钟分频设置
521     Sysctrl_SetHCLKDiv(SysctrlHclkDiv1);
522     Sysctrl_SetPCLKDiv(SysctrlPclkDiv1);
523 
524     return enRet;
525 }
526 
527 /**
528  *******************************************************************************
529  ** \brief 内部高速时钟频率TRIM值加载
530  ** \param [in]  enRCHFreq  设定的RCH目标频率值
531  ** \retval      Ok         设定成功
532  **             其他        设定失败或时钟未稳定
533  ******************************************************************************/
Sysctrl_SetRCHTrim(en_sysctrl_rch_freq_t enRCHFreq)534 en_result_t Sysctrl_SetRCHTrim(en_sysctrl_rch_freq_t enRCHFreq)
535 {
536     //加载RCH Trim值
537     M0P_SYSCTRL->RCH_CR_f.TRIM = *(RC_TRIM_BASE_ADDR + enRCHFreq);
538 
539     return Ok;
540 }
541 
542 /**
543  *******************************************************************************
544  ** \brief 外部高速时钟频率范围设定
545  ** \param [in]  enXTHFreq  设定的频率值
546  ** \retval      Ok         设定成功
547  **              其他       设定失败或时钟未稳定
548  ******************************************************************************/
Sysctrl_SetXTHFreq(en_sysctrl_xth_freq_t enXTHFreq)549 en_result_t Sysctrl_SetXTHFreq(en_sysctrl_xth_freq_t enXTHFreq)
550 {
551     en_result_t enRet = Ok;
552 
553     M0P_SYSCTRL->XTH_CR_f.XTH_FSEL = enXTHFreq;
554 
555     return enRet;
556 }
557 
558 /**
559  *******************************************************************************
560  ** \brief PLL时钟配置
561  ** \param [in]  pstcPLLCfg PLL配置结构体指针
562  ** \retval      Ok         设定成功
563  **              其他       设定失败或参数值不匹配
564  ******************************************************************************/
Sysctrl_SetPLLFreq(stc_sysctrl_pll_cfg_t * pstcPLLCfg)565 en_result_t Sysctrl_SetPLLFreq(stc_sysctrl_pll_cfg_t *pstcPLLCfg)
566 {
567     en_result_t enRet = Ok;
568 
569     uint16_t u16Trim[5] = {0};
570     u16Trim[4] = RCH_CR_TRIM_24M_VAL;
571     u16Trim[3] = RCH_CR_TRIM_22_12M_VAL;
572     u16Trim[2] = RCH_CR_TRIM_16M_VAL;
573     u16Trim[1] = RCH_CR_TRIM_8M_VAL;
574 
575     ////PLL最高时钟不能超过48MHz
576     //RCH作为PLL输入
577     if (SysctrlPllRch == pstcPLLCfg->enPllClkSrc)
578     {
579         if( ((u16Trim[4] == M0P_SYSCTRL->RCH_CR_f.TRIM) && (pstcPLLCfg->enPllMul > 2)) ||
580             ((u16Trim[3] == M0P_SYSCTRL->RCH_CR_f.TRIM) && (pstcPLLCfg->enPllMul > 2)) ||
581             ((u16Trim[2] == M0P_SYSCTRL->RCH_CR_f.TRIM) && (pstcPLLCfg->enPllMul > 3)) ||
582             ((u16Trim[1] == M0P_SYSCTRL->RCH_CR_f.TRIM) && (pstcPLLCfg->enPllMul > 6)))
583         {
584             return ErrorInvalidMode;
585         }
586     }
587     else    //XTH作为PLL输入
588     {
589         if ((SYSTEM_XTH * pstcPLLCfg->enPllMul) > 48*1000*1000)
590         {
591             return ErrorInvalidMode;
592         }
593     }
594 
595     M0P_SYSCTRL->PLL_CR_f.FRSEL  = pstcPLLCfg->enInFreq;
596     M0P_SYSCTRL->PLL_CR_f.FOSC   = pstcPLLCfg->enOutFreq;
597     M0P_SYSCTRL->PLL_CR_f.DIVN   = pstcPLLCfg->enPllMul;
598     M0P_SYSCTRL->PLL_CR_f.REFSEL = pstcPLLCfg->enPllClkSrc;
599 
600     return enRet;
601 }
602 
603 /**
604  *******************************************************************************
605  ** \brief 内部低速时钟频率TRIM值加载
606  ** \param [in]  enRCLFreq  设定的RCL目标频率值
607  ** \retval      Ok         设定成功
608  **             其他        设定失败
609  ******************************************************************************/
Sysctrl_SetRCLTrim(en_sysctrl_rcl_freq_t enRCLFreq)610 en_result_t Sysctrl_SetRCLTrim(en_sysctrl_rcl_freq_t enRCLFreq)
611 {
612     M0P_SYSCTRL->RCL_CR_f.TRIM = *(RC_TRIM_BASE_ADDR + enRCLFreq);
613 
614     return Ok;
615 }
616 
617 /**
618  *******************************************************************************
619  ** \brief 系统时钟(HCLK)分频设定
620  ** \param [in]  enHCLKDiv  分频设定值
621  ** \retval      Ok         设定成功
622  **             其他        设定失败
623  ******************************************************************************/
Sysctrl_SetHCLKDiv(en_sysctrl_hclk_div_t enHCLKDiv)624 en_result_t Sysctrl_SetHCLKDiv(en_sysctrl_hclk_div_t enHCLKDiv)
625 {
626     _SysctrlUnlock();
627     M0P_SYSCTRL->SYSCTRL0_f.HCLK_PRS = enHCLKDiv;
628 
629     return Ok;
630 }
631 
632 /**
633  *******************************************************************************
634  ** \brief 外设时钟(PCLK)分频设定
635  ** \param [in]  enPCLKDiv  分频设定值
636  ** \retval      Ok         设定成功
637  **             其他        设定失败
638  ******************************************************************************/
Sysctrl_SetPCLKDiv(en_sysctrl_pclk_div_t enPCLKDiv)639 en_result_t Sysctrl_SetPCLKDiv(en_sysctrl_pclk_div_t enPCLKDiv)
640 {
641     _SysctrlUnlock();
642     M0P_SYSCTRL->SYSCTRL0_f.PCLK_PRS = enPCLKDiv;
643 
644     return Ok;
645 }
646 
647 ///<< for Sysctrl_SetPeripheralGate() & Sysctrl_GetPeripheralGate()
648 static volatile boolean_t bDacPeriBac = FALSE;
649 
650 /**
651  *******************************************************************************
652  ** \brief 设置外设时钟门控开关
653  ** \param [in]  enPeripheral   目标外设
654  ** \param [in]  bFlag          使能开关
655  ** \retval      Ok             设定成功
656  **             其他            设定失败
657  ******************************************************************************/
Sysctrl_SetPeripheralGate(en_sysctrl_peripheral_gate_t enPeripheral,boolean_t bFlag)658 en_result_t Sysctrl_SetPeripheralGate(en_sysctrl_peripheral_gate_t enPeripheral, boolean_t bFlag)
659 {
660     if(enPeripheral&0x20u)
661     {
662         enPeripheral &= ~0x20u;
663         SetBit((uint32_t)(&(M0P_SYSCTRL->PERI_CLKEN1)), enPeripheral, bFlag);
664 
665         if((SysctrlPeripheralDac & ~0x20u) == enPeripheral)
666         {
667             bDacPeriBac = bFlag;
668         }
669         else
670         {
671             SetBit((uint32_t)(&(M0P_SYSCTRL->PERI_CLKEN1)), (SysctrlPeripheralDac & ~0x20u), bDacPeriBac);
672         }
673     }
674     else
675     {
676         SetBit((uint32_t)(&(M0P_SYSCTRL->PERI_CLKEN0)), enPeripheral, bFlag);
677     }
678 
679     return Ok;
680 }
681 
682 /**
683  *******************************************************************************
684  ** \brief 获得外设时钟门控开关状态
685  ** \param [in]  enPeripheral   目标外设
686  ** \retval      TRUE           开
687  **              FALSE          关
688  ******************************************************************************/
Sysctrl_GetPeripheralGate(en_sysctrl_peripheral_gate_t enPeripheral)689 boolean_t Sysctrl_GetPeripheralGate(en_sysctrl_peripheral_gate_t enPeripheral)
690 {
691     if(enPeripheral&0x20u)
692     {
693         if(SysctrlPeripheralDac == enPeripheral)
694         {
695             return bDacPeriBac;
696         }
697         else
698         {
699             enPeripheral &= ~0x20u;
700             return GetBit((uint32_t)(&(M0P_SYSCTRL->PERI_CLKEN1)), enPeripheral);
701         }
702 
703     }
704     else
705     {
706         return GetBit((uint32_t)(&(M0P_SYSCTRL->PERI_CLKEN0)), enPeripheral);
707     }
708 
709 }
710 
711 /**
712  *******************************************************************************
713  ** \brief 系统功能设定
714  ** \param [in]  enFunc     系统功能枚举类型
715  ** \param [in]  bFlag      1-开/0-关
716  ** \retval      Ok         设定成功
717  **             其他        设定失败
718  ******************************************************************************/
Sysctrl_SetFunc(en_sysctrl_func_t enFunc,boolean_t bFlag)719 en_result_t Sysctrl_SetFunc(en_sysctrl_func_t enFunc, boolean_t bFlag)
720 {
721     _SysctrlUnlock();
722     SetBit((uint32_t)(&(M0P_SYSCTRL->SYSCTRL1)), enFunc, bFlag);
723 
724     return Ok;
725 }
726 
727 /**
728  *******************************************************************************
729  ** \brief 设定RTC校准时钟频率
730  ** \param [in]  enRtcAdj   校准频率值
731  ** \retval      Ok         设定成功
732  **             其他        设定失败
733  ******************************************************************************/
Sysctrl_SetRTCAdjustClkFreq(en_sysctrl_rtc_adjust_t enRtcAdj)734 en_result_t Sysctrl_SetRTCAdjustClkFreq(en_sysctrl_rtc_adjust_t enRtcAdj)
735 {
736     _SysctrlUnlock();
737     M0P_SYSCTRL->SYSCTRL1_f.RTC_FREQ_ADJUST = enRtcAdj;
738 
739     return Ok;
740 }
741 
742 //@} // SysctrlGroup
743 
744 /*******************************************************************************
745  * EOF (not truncated)
746  ******************************************************************************/
747