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 "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 RCH_CR_TRIM_24M_VAL         (*((volatile uint16_t*) (0x00100C00ul)))
85 #define RCH_CR_TRIM_22_12M_VAL      (*((volatile uint16_t*) (0x00100C02ul)))
86 #define RCH_CR_TRIM_16M_VAL         (*((volatile uint16_t*) (0x00100C04ul)))
87 #define RCH_CR_TRIM_8M_VAL          (*((volatile uint16_t*) (0x00100C06ul)))
88 #define RCH_CR_TRIM_4M_VAL          (*((volatile uint16_t*) (0x00100C08ul)))
89 
90 #define RCL_CR_TRIM_38400_VAL       (*((volatile uint16_t*) (0x00100C20ul)))
91 #define RCL_CR_TRIM_32768_VAL       (*((volatile uint16_t*) (0x00100C22ul)))
92 
93 /*******************************************************************************
94  * Global variable definitions (declared in header file with 'extern')
95  ******************************************************************************/
96 extern uint32_t SystemCoreClock;
97 /*******************************************************************************
98  * Local type definitions ('typedef')
99  ******************************************************************************/
100 
101 /*******************************************************************************
102  * Local variable definitions ('static')
103  ******************************************************************************/
104 
105 /*******************************************************************************
106  * Local function prototypes ('static')
107  ******************************************************************************/
108 
109 
110 /*******************************************************************************
111  * Function implementation - global ('extern') and local ('static')
112  ******************************************************************************/
113 
114 /**
115  *******************************************************************************
116  ** \brief SYSCTRL0\SYSCTRL1寄存器操作解锁
117  **
118  ** \retval None
119  ******************************************************************************/
_SysctrlUnlock(void)120 static void _SysctrlUnlock(void)
121 {
122     M0P_SYSCTRL->SYSCTRL2 = 0x5A5A;
123     M0P_SYSCTRL->SYSCTRL2 = 0xA5A5;
124 }
125 
126 /**
127  *******************************************************************************
128  ** \brief 系统时钟源使能
129  ** \param [in]  enSource   目标时钟源
130  ** \param [in]  bFlag      使能1-开/0-关
131  ** \retval      Ok         设定成功
132  **             其他        设定失败
133  ******************************************************************************/
Sysctrl_ClkSourceEnable(en_sysctrl_clk_source_t enSource,boolean_t bFlag)134 en_result_t Sysctrl_ClkSourceEnable(en_sysctrl_clk_source_t enSource, boolean_t bFlag)
135 {
136     en_result_t enRet = Ok;
137 
138     _SysctrlUnlock();
139     bFlag = !!bFlag;
140 
141     switch (enSource)
142     {
143         case SysctrlClkRCH:
144             M0P_SYSCTRL->SYSCTRL0_f.RCH_EN = bFlag;
145             while(bFlag && (1 != M0P_SYSCTRL->RCH_CR_f.STABLE))
146             {
147                 ;
148             }
149             break;
150 
151         case SysctrlClkXTH:
152             M0P_GPIO->PDADS_f.PD00 = 1;
153             M0P_GPIO->PDADS_f.PD01 = 1;
154             M0P_SYSCTRL->SYSCTRL0_f.XTH_EN = bFlag;
155             while(bFlag && (1 != M0P_SYSCTRL->XTH_CR_f.STABLE))
156             {
157                 ;
158             }
159             break;
160 
161         case SysctrlClkRCL:
162             M0P_SYSCTRL->SYSCTRL0_f.RCL_EN = bFlag;
163             while(bFlag && (1 != M0P_SYSCTRL->RCL_CR_f.STABLE))
164             {
165                 ;
166             }
167             break;
168 
169         case SysctrlClkXTL:
170             M0P_GPIO->PCADS_f.PC14 = 1;
171             M0P_GPIO->PCADS_f.PC15 = 1;
172             M0P_SYSCTRL->SYSCTRL0_f.XTL_EN = bFlag;
173             while(bFlag && (1 != M0P_SYSCTRL->XTL_CR_f.STABLE))
174             {
175                 ;
176             }
177             break;
178 
179         case SysctrlClkPLL:
180             M0P_SYSCTRL->SYSCTRL0_f.PLL_EN = bFlag;
181             while(bFlag && (1 != M0P_SYSCTRL->PLL_CR_f.STABLE))
182             {
183                 ;
184             }
185             break;
186 
187         default:
188             enRet = ErrorInvalidParameter;
189             break;
190     }
191 
192     return enRet;
193 }
194 
195 /**
196  *******************************************************************************
197  ** \brief 外部高速晶振驱动配置
198  ** \param [in]  enFreq     外部高速晶振频率范围选择
199  ** \param [in]  enDriver   外部高速晶振驱动能力选择
200  ** \retval      Ok         设定成功
201  **             其他        设定失败
202  ******************************************************************************/
Sysctrl_XTHDriverConfig(en_sysctrl_xtal_driver_t enDriver)203 en_result_t Sysctrl_XTHDriverConfig(en_sysctrl_xtal_driver_t enDriver)
204 {
205     en_result_t enRet = Ok;
206 
207     M0P_SYSCTRL->XTH_CR_f.DRIVER   = enDriver;
208 
209     return enRet;
210 }
211 
212 /**
213  *******************************************************************************
214  ** \brief 外部低速晶振驱动配置
215  ** \param [in]  enFreq     外部低速晶振频率范围选择
216  ** \param [in]  enDriver   外部低速晶振驱动能力选择
217  ** \retval      Ok         设定成功
218  **             其他        设定失败
219  ******************************************************************************/
Sysctrl_XTLDriverConfig(en_sysctrl_xtl_amp_t enAmp,en_sysctrl_xtal_driver_t enDriver)220 en_result_t Sysctrl_XTLDriverConfig(en_sysctrl_xtl_amp_t enAmp, en_sysctrl_xtal_driver_t enDriver)
221 {
222     en_result_t enRet = Ok;
223 
224     M0P_SYSCTRL->XTL_CR_f.AMP_SEL = enAmp;
225     M0P_SYSCTRL->XTL_CR_f.DRIVER  = enDriver;
226 
227     return enRet;
228 }
229 
230 /**
231  *******************************************************************************
232  ** \brief 外部高速时钟稳定周期配置
233  ** \param [in]  enCycle     外部高速时钟稳定周期设置
234  ** \retval      Ok         设定成功
235  **             其他        设定失败
236  ******************************************************************************/
Sysctrl_SetXTHStableTime(en_sysctrl_xth_cycle_t enCycle)237 en_result_t Sysctrl_SetXTHStableTime(en_sysctrl_xth_cycle_t enCycle)
238 {
239     en_result_t enRet = Ok;
240     M0P_SYSCTRL->XTH_CR_f.STARTUP = enCycle;
241     return enRet;
242 }
243 
244 /**
245  *******************************************************************************
246  ** \brief 内部低速时钟稳定周期配置
247  ** \param [in]  enCycle     内部低速时钟稳定周期设置
248  ** \retval      Ok         设定成功
249  **             其他        设定失败
250  ******************************************************************************/
Sysctrl_SetRCLStableTime(en_sysctrl_rcl_cycle_t enCycle)251 en_result_t Sysctrl_SetRCLStableTime(en_sysctrl_rcl_cycle_t enCycle)
252 {
253     en_result_t enRet = Ok;
254     M0P_SYSCTRL->RCL_CR_f.STARTUP = enCycle;
255     return enRet;
256 }
257 
258 /**
259  *******************************************************************************
260  ** \brief 外部低速时钟稳定周期配置
261  ** \param [in]  enCycle     外部低速时钟稳定周期设置
262  ** \retval      Ok         设定成功
263  **             其他        设定失败
264  ******************************************************************************/
Sysctrl_SetXTLStableTime(en_sysctrl_xtl_cycle_t enCycle)265 en_result_t Sysctrl_SetXTLStableTime(en_sysctrl_xtl_cycle_t enCycle)
266 {
267     en_result_t enRet = Ok;
268     M0P_SYSCTRL->XTL_CR_f.STARTUP = enCycle;
269     return enRet;
270 }
271 
272 /**
273  *******************************************************************************
274  ** \brief PLL稳定周期配置
275  ** \param [in]  enCycle    PLL稳定周期设置
276  ** \retval      Ok         设定成功
277  **             其他        设定失败
278  ******************************************************************************/
Sysctrl_SetPLLStableTime(en_sysctrl_pll_cycle_t enCycle)279 en_result_t Sysctrl_SetPLLStableTime(en_sysctrl_pll_cycle_t enCycle)
280 {
281     en_result_t enRet = Ok;
282     M0P_SYSCTRL->PLL_CR_f.STARTUP = enCycle;
283     return enRet;
284 }
285 
286 /**
287  *******************************************************************************
288  ** \brief 时钟源切换,该函数执行后会开启新时钟源
289  ** \note  选择时钟源之前,需根据需要配置目标时钟源的频率/驱动参数/使能时钟源等
290  ** \param [in]  enSource   新时钟源
291  **
292  ** \retval      Ok         设定成功
293  **              其他       设定失败
294  ******************************************************************************/
Sysctrl_SysClkSwitch(en_sysctrl_clk_source_t enSource)295 en_result_t Sysctrl_SysClkSwitch(en_sysctrl_clk_source_t enSource)
296 {
297     en_result_t enRet = Ok;
298 
299     en_sysctrl_clk_source_t ClkNew = enSource;
300 
301     _SysctrlUnlock();
302     M0P_SYSCTRL->SYSCTRL0_f.CLK_SW5_SEL = ClkNew;
303 
304     //更新Core时钟(HCLK)
305     SystemCoreClockUpdate();
306 
307     return enRet;
308 }
309 
310 /**
311  *******************************************************************************
312  ** \brief   获得系统时钟(HCLK)频率值
313  ** \retval  uint32_t         HCLK频率值
314  **
315  ******************************************************************************/
Sysctrl_GetHClkFreq(void)316 uint32_t Sysctrl_GetHClkFreq(void)
317 {
318     uint32_t u32Val = 0;
319     const uint32_t u32hcr_tbl[] = { 4000000, 8000000, 16000000, 22120000, 24000000};
320     const uint16_t u32lcr_tbl[] = { 32768, 38400};
321     en_sysctrl_clk_source_t enSrc;
322     uint16_t u16Trim[5] = {0};
323     u16Trim[4] = RCH_CR_TRIM_24M_VAL;
324     u16Trim[3] = RCH_CR_TRIM_22_12M_VAL;
325     u16Trim[2] = RCH_CR_TRIM_16M_VAL;
326     u16Trim[1] = RCH_CR_TRIM_8M_VAL;
327     u16Trim[0] = RCL_CR_TRIM_38400_VAL;
328 
329     //获取当前系统时钟
330     enSrc = (en_sysctrl_clk_source_t)(M0P_SYSCTRL->SYSCTRL0_f.CLK_SW5_SEL);
331 
332     switch (enSrc)
333     {
334         case SysctrlClkRCH:
335             {
336 
337                 if((M0P_SYSCTRL->RCH_CR_f.TRIM) == (u16Trim[4]))
338                 {
339                     u32Val = u32hcr_tbl[4];
340                 }
341                 else if((M0P_SYSCTRL->RCH_CR_f.TRIM) == (u16Trim[3]))
342                 {
343                     u32Val = u32hcr_tbl[3];
344                 }
345                 else if((M0P_SYSCTRL->RCH_CR_f.TRIM) == (u16Trim[2]))
346                 {
347                     u32Val = u32hcr_tbl[2];
348                 }
349                 else if((M0P_SYSCTRL->RCH_CR_f.TRIM) == (u16Trim[1]))
350                 {
351                     u32Val = u32hcr_tbl[1];
352                 }
353                 else
354                 {
355                     u32Val = u32hcr_tbl[0];
356                 }
357             }
358             break;
359         case SysctrlClkXTH:
360             u32Val = SYSTEM_XTH;
361             break;
362         case SysctrlClkRCL:
363             {
364                 if(u16Trim[0] == (M0P_SYSCTRL->RCL_CR_f.TRIM))
365                 {
366                     u32Val = u32lcr_tbl[1];
367                 }
368                 else
369                 {
370                     u32Val = u32lcr_tbl[0];
371                 }
372             }
373             break;
374         case SysctrlClkXTL:
375             u32Val = SYSTEM_XTL;
376             break;
377         case SysctrlClkPLL:
378             {
379                 if (SysctrlPllRch == M0P_SYSCTRL->PLL_CR_f.REFSEL)
380                 {
381                     if(u16Trim[4] == M0P_SYSCTRL->RCH_CR_f.TRIM)
382                     {
383                         u32Val = u32hcr_tbl[4];
384                     }
385                     else if(u16Trim[3] == M0P_SYSCTRL->RCH_CR_f.TRIM)
386                     {
387                         u32Val = u32hcr_tbl[3];
388                     }
389                     else if(u16Trim[2] == M0P_SYSCTRL->RCH_CR_f.TRIM)
390                     {
391                         u32Val = u32hcr_tbl[2];
392                     }
393                     else if(u16Trim[1] == M0P_SYSCTRL->RCH_CR_f.TRIM)
394                     {
395                         u32Val = u32hcr_tbl[1];
396                     }
397                     else
398                     {
399                         u32Val = u32hcr_tbl[0];
400                     }
401                 }
402                 else
403                 {
404                     u32Val = SYSTEM_XTH;
405                 }
406 
407                 u32Val = (u32Val * M0P_SYSCTRL->PLL_CR_f.DIVN);
408             }
409             break;
410         default:
411             u32Val = 0u;
412             break;
413     }
414 
415     u32Val = (u32Val >> M0P_SYSCTRL->SYSCTRL0_f.HCLK_PRS);
416 
417     return u32Val;
418 }
419 
420 /**
421  *******************************************************************************
422  ** \brief 获得外设时钟(PCLK)频率值
423  ** \retval uint32_t   PCLK频率值(Hz)
424  **
425  ******************************************************************************/
Sysctrl_GetPClkFreq(void)426 uint32_t Sysctrl_GetPClkFreq(void)
427 {
428     uint32_t u32Val = 0;
429 
430     u32Val = Sysctrl_GetHClkFreq();
431     u32Val = (u32Val >> (M0P_SYSCTRL->SYSCTRL0_f.PCLK_PRS));
432 
433     return u32Val;
434 }
435 
436 
437 /**
438  *******************************************************************************
439  ** \brief 时钟初始化函数
440  ** \param [in]  pstcCfg    初始化配置参数
441  ** \retval      Ok         设定成功
442  **             其他        设定失败
443  ******************************************************************************/
Sysctrl_ClkInit(stc_sysctrl_clk_config_t * pstcCfg)444 en_result_t Sysctrl_ClkInit(stc_sysctrl_clk_config_t *pstcCfg)
445 {
446     en_result_t enRet = Ok;
447 
448     //系统时钟参数配置
449     switch(pstcCfg->enClkSrc)
450     {
451         case SysctrlClkRCH:
452 
453             break;
454         case SysctrlClkXTH:
455             Sysctrl_XTHDriverConfig(SysctrlXtalDriver3);
456             Sysctrl_SetXTHStableTime(SysctrlXthStableCycle16384);
457             break;
458         case SysctrlClkRCL:
459             Sysctrl_SetRCLStableTime(SysctrlRclStableCycle256);
460             break;
461         case SysctrlClkXTL:
462             Sysctrl_XTLDriverConfig(SysctrlXtlAmp3, SysctrlXtalDriver3);
463             Sysctrl_SetXTLStableTime(SysctrlXtlStableCycle16384);
464             break;
465         case SysctrlClkPLL:
466             Sysctrl_SetPLLStableTime(SysctrlPllStableCycle16384);
467             break;
468         default:
469             enRet = ErrorInvalidParameter;
470             break;
471     }
472 
473     //时钟源使能
474     Sysctrl_ClkSourceEnable(pstcCfg->enClkSrc, TRUE);
475 
476     //时钟源切换
477     Sysctrl_SysClkSwitch(pstcCfg->enClkSrc);
478 
479     //时钟分频设置
480     Sysctrl_SetHCLKDiv(pstcCfg->enHClkDiv);
481     Sysctrl_SetPCLKDiv(pstcCfg->enPClkDiv);
482 
483     return enRet;
484 }
485 
486 /**
487  *******************************************************************************
488  ** \brief 时钟去初始化函数
489  ** \param [in]
490  ** \retval      Ok         设定成功
491  **             其他        设定失败
492  ******************************************************************************/
Sysctrl_ClkDeInit(void)493 en_result_t Sysctrl_ClkDeInit(void)
494 {
495     en_result_t enRet = Ok;
496 
497     //配置RCH为内部4Hz
498     Sysctrl_SetRCHTrim(SysctrlRchFreq4MHz);
499 
500     //时钟源使能
501     Sysctrl_ClkSourceEnable(SysctrlClkRCH, TRUE);
502 
503     //时钟源切换
504     Sysctrl_SysClkSwitch(SysctrlClkRCH);
505 
506     //其它时钟源使能关闭
507     Sysctrl_ClkSourceEnable(SysctrlClkXTH, FALSE);
508     Sysctrl_ClkSourceEnable(SysctrlClkRCL, FALSE);
509     Sysctrl_ClkSourceEnable(SysctrlClkXTL, FALSE);
510     Sysctrl_ClkSourceEnable(SysctrlClkPLL, FALSE);
511 
512     //时钟分频设置
513     Sysctrl_SetHCLKDiv(SysctrlHclkDiv1);
514     Sysctrl_SetPCLKDiv(SysctrlPclkDiv1);
515 
516     return enRet;
517 }
518 
519 /**
520  *******************************************************************************
521  ** \brief 内部高速时钟频率TRIM值加载
522  ** \param [in]  enRCHFreq  设定的RCH目标频率值
523  ** \retval      Ok         设定成功
524  **             其他        设定失败或时钟未稳定
525  ******************************************************************************/
Sysctrl_SetRCHTrim(en_sysctrl_rch_freq_t enRCHFreq)526 en_result_t Sysctrl_SetRCHTrim(en_sysctrl_rch_freq_t enRCHFreq)
527 {
528     en_result_t enRet = Ok;
529 
530     //加载RCH Trim值
531     switch (enRCHFreq)
532     {
533         case SysctrlRchFreq4MHz:
534             M0P_SYSCTRL->RCH_CR_f.TRIM = RCH_CR_TRIM_4M_VAL;
535             break;
536         case SysctrlRchFreq8MHz:
537             M0P_SYSCTRL->RCH_CR_f.TRIM = RCH_CR_TRIM_8M_VAL;
538             break;
539         case SysctrlRchFreq16MHz:
540             M0P_SYSCTRL->RCH_CR_f.TRIM = RCH_CR_TRIM_16M_VAL;
541             break;
542         case SysctrlRchFreq22_12MHz:
543             M0P_SYSCTRL->RCH_CR_f.TRIM = RCH_CR_TRIM_22_12M_VAL;
544             break;
545         case SysctrlRchFreq24MHz:
546             M0P_SYSCTRL->RCH_CR_f.TRIM = RCH_CR_TRIM_24M_VAL;
547             break;
548         default:
549             enRet = ErrorInvalidParameter;
550             break;
551     }
552 
553     return enRet;
554 }
555 
556 /**
557  *******************************************************************************
558  ** \brief 外部高速时钟频率范围设定
559  ** \param [in]  enXTHFreq  设定的频率值
560  ** \retval      Ok         设定成功
561  **              其他       设定失败或时钟未稳定
562  ******************************************************************************/
Sysctrl_SetXTHFreq(en_sysctrl_xth_freq_t enXTHFreq)563 en_result_t Sysctrl_SetXTHFreq(en_sysctrl_xth_freq_t enXTHFreq)
564 {
565     en_result_t enRet = Ok;
566 
567     M0P_SYSCTRL->XTH_CR_f.XTH_FSEL = enXTHFreq;
568 
569     return enRet;
570 }
571 
572 /**
573  *******************************************************************************
574  ** \brief PLL时钟配置
575  ** \param [in]  pstcPLLCfg PLL配置结构体指针
576  ** \retval      Ok         设定成功
577  **              其他       设定失败或参数值不匹配
578  ******************************************************************************/
Sysctrl_SetPLLFreq(stc_sysctrl_pll_config_t * pstcPLLCfg)579 en_result_t Sysctrl_SetPLLFreq(stc_sysctrl_pll_config_t *pstcPLLCfg)
580 {
581     en_result_t enRet = Ok;
582 
583     uint16_t u16Trim[5] = {0};
584     u16Trim[4] = RCH_CR_TRIM_24M_VAL;
585     u16Trim[3] = RCH_CR_TRIM_22_12M_VAL;
586     u16Trim[2] = RCH_CR_TRIM_16M_VAL;
587     u16Trim[1] = RCH_CR_TRIM_8M_VAL;
588 
589     ////PLL最高时钟不能超过48MHz
590     //RCH作为PLL输入
591     if (SysctrlPllRch == pstcPLLCfg->enPllClkSrc)
592     {
593         if( ((u16Trim[4] == M0P_SYSCTRL->RCH_CR_f.TRIM) && (pstcPLLCfg->enPllMul > 2)) ||
594             ((u16Trim[3] == M0P_SYSCTRL->RCH_CR_f.TRIM) && (pstcPLLCfg->enPllMul > 2)) ||
595             ((u16Trim[2] == M0P_SYSCTRL->RCH_CR_f.TRIM) && (pstcPLLCfg->enPllMul > 3)) ||
596             ((u16Trim[1] == M0P_SYSCTRL->RCH_CR_f.TRIM) && (pstcPLLCfg->enPllMul > 6)))
597         {
598             return ErrorInvalidMode;
599         }
600     }
601     else    //XTH作为PLL输入
602     {
603         if ((SYSTEM_XTH * pstcPLLCfg->enPllMul) > 48*1000*1000)
604         {
605             return ErrorInvalidMode;
606         }
607     }
608 
609     M0P_SYSCTRL->PLL_CR_f.FRSEL  = pstcPLLCfg->enInFreq;
610     M0P_SYSCTRL->PLL_CR_f.FOSC   = pstcPLLCfg->enOutFreq;
611     M0P_SYSCTRL->PLL_CR_f.DIVN   = pstcPLLCfg->enPllMul;
612     M0P_SYSCTRL->PLL_CR_f.REFSEL = pstcPLLCfg->enPllClkSrc;
613 
614     return enRet;
615 }
616 
617 /**
618  *******************************************************************************
619  ** \brief 内部低速时钟频率TRIM值加载
620  ** \param [in]  enRCLFreq  设定的RCL目标频率值
621  ** \retval      Ok         设定成功
622  **             其他        设定失败
623  ******************************************************************************/
Sysctrl_SetRCLTrim(en_sysctrl_rcl_freq_t enRCLFreq)624 en_result_t Sysctrl_SetRCLTrim(en_sysctrl_rcl_freq_t enRCLFreq)
625 {
626     en_result_t enRet = Ok;
627 
628     switch (enRCLFreq)
629     {
630         case SysctrlRclFreq32768:
631             M0P_SYSCTRL->RCL_CR_f.TRIM = RCL_CR_TRIM_32768_VAL;
632             break;
633         case SysctrlRclFreq38400:
634             M0P_SYSCTRL->RCL_CR_f.TRIM = RCL_CR_TRIM_38400_VAL;
635             break;
636         default:
637             enRet = ErrorInvalidParameter;
638             break;
639     }
640 
641     return enRet;
642 }
643 
644 /**
645  *******************************************************************************
646  ** \brief 系统时钟(HCLK)分频设定
647  ** \param [in]  enHCLKDiv  分频设定值
648  ** \retval      Ok         设定成功
649  **             其他        设定失败
650  ******************************************************************************/
Sysctrl_SetHCLKDiv(en_sysctrl_hclk_div_t enHCLKDiv)651 en_result_t Sysctrl_SetHCLKDiv(en_sysctrl_hclk_div_t enHCLKDiv)
652 {
653     en_result_t enRet = Ok;
654 
655     _SysctrlUnlock();
656     M0P_SYSCTRL->SYSCTRL0_f.HCLK_PRS = enHCLKDiv;
657 
658     return enRet;
659 }
660 
661 /**
662  *******************************************************************************
663  ** \brief 外设时钟(PCLK)分频设定
664  ** \param [in]  enPCLKDiv  分频设定值
665  ** \retval      Ok         设定成功
666  **             其他        设定失败
667  ******************************************************************************/
Sysctrl_SetPCLKDiv(en_sysctrl_pclk_div_t enPCLKDiv)668 en_result_t Sysctrl_SetPCLKDiv(en_sysctrl_pclk_div_t enPCLKDiv)
669 {
670     en_result_t enRet = Ok;
671 
672     _SysctrlUnlock();
673     M0P_SYSCTRL->SYSCTRL0_f.PCLK_PRS = enPCLKDiv;
674 
675     return enRet;
676 }
677 
678 /**
679  *******************************************************************************
680  ** \brief 设置外设时钟门控开关
681  ** \param [in]  enPeripheral   目标外设
682  ** \param [in]  bFlag          使能开关
683  ** \retval      Ok             设定成功
684  **             其他            设定失败
685  ******************************************************************************/
Sysctrl_SetPeripheralGate(en_sysctrl_peripheral_gate_t enPeripheral,boolean_t bFlag)686 en_result_t Sysctrl_SetPeripheralGate(en_sysctrl_peripheral_gate_t enPeripheral, boolean_t bFlag)
687 {
688     en_result_t enRet = Ok;
689 
690     bFlag = !!bFlag;
691 
692     setBit(&(M0P_SYSCTRL->PERI_CLKEN), enPeripheral, bFlag);
693 
694     return enRet;
695 }
696 
697 /**
698  *******************************************************************************
699  ** \brief 获得外设时钟门控开关状态
700  ** \param [in]  enPeripheral   目标外设
701  ** \retval      TRUE           开
702  **              FALSE          关
703  ******************************************************************************/
Sysctrl_GetPeripheralGate(en_sysctrl_peripheral_gate_t enPeripheral)704 boolean_t Sysctrl_GetPeripheralGate(en_sysctrl_peripheral_gate_t enPeripheral)
705 {
706     return getBit(&(M0P_SYSCTRL->PERI_CLKEN), enPeripheral);
707 }
708 
709 /**
710  *******************************************************************************
711  ** \brief 系统功能设定
712  ** \param [in]  enFunc     系统功能枚举类型
713  ** \param [in]  bFlag      1-开/0-关
714  ** \retval      Ok         设定成功
715  **             其他        设定失败
716  ******************************************************************************/
Sysctrl_SetFunc(en_sysctrl_func_t enFunc,boolean_t bFlag)717 en_result_t Sysctrl_SetFunc(en_sysctrl_func_t enFunc, boolean_t bFlag)
718 {
719     en_result_t enRet = Ok;
720 
721     _SysctrlUnlock();
722     bFlag = !!bFlag;
723 
724     switch (enFunc)
725     {
726         case SysctrlWkupByRCHEn:
727             M0P_SYSCTRL->SYSCTRL0_f.WAKEUP_BYRCH = bFlag;
728             break;
729         case SysctrlEXTHEn:
730             M0P_SYSCTRL->SYSCTRL1_f.EXTH_EN = bFlag;
731             break;
732         case SysctrlEXTLEn:
733             M0P_SYSCTRL->SYSCTRL1_f.EXTL_EN = bFlag;
734             break;
735         case SysctrlXTLAlwaysOnEn:
736             M0P_SYSCTRL->SYSCTRL1_f.XTL_ALWAYS_ON = bFlag;
737             break;
738         case SysctrlClkFuncRTCLpmEn:
739             M0P_SYSCTRL->SYSCTRL1_f.RTC_LPW = bFlag;
740             break;
741         case SysctrlCMLockUpEn:
742             M0P_SYSCTRL->SYSCTRL1_f.LOCKUP_EN = bFlag;
743             break;
744         case SysctrlSWDUseIOEn:
745             M0P_SYSCTRL->SYSCTRL1_f.SWD_USE_IO = bFlag;
746             break;
747         default:
748             enRet = ErrorInvalidParameter;
749             break;
750     }
751 
752     return enRet;
753 }
754 
755 /**
756  *******************************************************************************
757  ** \brief 设定RTC校准时钟频率
758  ** \param [in]  enRtcAdj   校准频率值
759  ** \retval      Ok         设定成功
760  **             其他        设定失败
761  ******************************************************************************/
Sysctrl_SetRTCAdjustClkFreq(en_sysctrl_rtc_adjust_t enRtcAdj)762 en_result_t Sysctrl_SetRTCAdjustClkFreq(en_sysctrl_rtc_adjust_t enRtcAdj)
763 {
764     en_result_t enRet = Ok;
765 
766     _SysctrlUnlock();
767     M0P_SYSCTRL->SYSCTRL1_f.RTC_FREQ_ADJUST = enRtcAdj;
768 
769     return enRet;
770 }
771 
772 //@} // SysctrlGroup
773 
774 /*******************************************************************************
775  * EOF (not truncated)
776  ******************************************************************************/
777