86.
s pin
PORTE_PCR25 = PORT_PCR_MUX(0x3); // UART is alt3 function for thi }
if (TERM_PORT == UART5_BASE_PTR) {
/* Enable the UART3_TXD function on PTC17 */
PORTE_PCR8 = PORT_PCR_MUX(0x3); // UART is alt3 function for this
87. 88. 89. 90. 91.
pin
92. 93. 94.
pin
/* Enable the UART3_RXD function on PTC16 */
PORTE_PCR9 = PORT_PCR_MUX(0x3); // UART is alt3 function for this }
/* UART0 and UART1 are clocked from the core clock, but all other UA * clocked from the peripheral clock. So we have to determine whic * to send to the uart_init function. */
if ((TERM_PORT == UART0_BASE_PTR) | (TERM_PORT == UART1_BASE_PTR)) uart_init (TERM_PORT, core_clk_khz, TERMINAL_BAUD); else
uart_init (TERM_PORT, periph_clk_khz, TERMINAL_BAUD); }
/********************************************************************/ void trace_clk_init(void) {
/* Set the trace clock to the core clock frequency */ SIM_SOPT2 |= SIM_SOPT2_TRACECLKSEL_MASK;
95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123.
RTs are h clock
/* Enable the TRACE_CLKOUT pin function on PTA6 (alt7 function) */ PORTA_PCR6 = ( PORT_PCR_MUX(0x7)); }
/********************************************************************/ void fb_clk_init(void) {
/* Enable the clock to the FlexBus module */ SIM_SCGC7 |= SIM_SCGC7_FLEXBUS_MASK;
/* Enable the FB_CLKOUT function on PTC3 (alt5 function) */ PORTC_PCR3 = ( PORT_PCR_MUX(0x5)); }
/********************************************************************/
首先写SIM_SCGC5寄存器。SCGC5表示的是System Clock Gating Control Register 5(系统时钟门控制寄存器5).系统集成模块 --System integration module (SIM)--控制寄存器组中共有8个SCGC寄存器,它们分别控制不同外设所需要的时钟的开关,SCGC5寄存器控制的是PORTA~PORTE、TSI、REGFILE和LPTIMER时钟的开关,向对应的位写入1表示使能时钟。第一段代码分别打开了PORTA~PORTE的时钟开关。
上面pll_init(unsigned char,unsigned char)函数用来增加系统时钟。 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27.
ialize
unsigned char pll_init(unsigned char clk_option, unsigned char crystal_val) {
unsigned char pll_freq;
if (clk_option > 3) {return 0;} //return 0 if one of the available option
s is not selected
if (crystal_val > 15) {return 1;} // return 1 if one of the available cry
stal options is not available
//This assumes that the MCG is in default FEI mode out of reset.
// First move to FBE mode
#if (defined(K60_CLK) || defined(ASB817)) MCG_C2 = 0; #else
// Enable external oscillator, RANGE=2, HGO=1, EREFS=1, LP=0, IRCS=0 MCG_C2 = MCG_C2_RANGE(2) | MCG_C2_HGO_MASK | MCG_C2_EREFS_MASK; #endif
// after initialization of oscillator release latched state of oscillato SIM_SCGC4 |= SIM_SCGC4_LLWU_MASK; LLWU_CS |= LLWU_CS_ACKISO_MASK;
// Select external oscilator and Reference Divider and clear IREFS to start// CLKS=2, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0 MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3);
r and GPIO
ext osc
/* if we aren't using an osc input we don't need to wait for the osc t#if (!defined(K60_CLK) && !defined(ASB817))
while (!(MCG_S & MCG_S_OSCINIT_MASK)){}; // wait for oscillator to init#endif
o init */
28. 29.
30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59.
/4
while (MCG_S & MCG_S_IREFST_MASK){}; // wait for Reference clock Status b
it to clear
while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2){}; // Wa
it for clock status bits to show clock source is ext ref clk
// Now in FBE
#if (defined(K60_CLK))
MCG_C5 = MCG_C5_PRDIV(0x18); #else
// Configure PLL Ref Divider, PLLCLKEN=0, PLLSTEN=0, PRDIV=5
// The crystal frequency is used to select the PRDIV value. Only even frequ// that will produce a 2MHz reference clock to the PLL.
MCG_C5 = MCG_C5_PRDIV(crystal_val); // Set PLL ref divider to match the c#endif
ency crystals are supported
rystal used
// Ensure MCG_C6 is at the reset default of 0. LOLIE disabled, PLL disab MCG_C6 = 0x0;
// Select the PLL VCO divider and system clock dividers depending on clocki switch (clk_option) { case 0:
// Set system options dividers
//MCG=PLL, core = MCG, bus = MCG, FlexBus = MCG, Flash clock= MCG/2 set_sys_dividers(0,0,0,1);
// Set the VCO divider and enable the PLL for 50MHz, LOLIE=0, PLLS= MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(1); //VDIV = 1 (x25) pll_freq = 50; break; case 1:
// Set system options dividers
//MCG=PLL, core = MCG, bus = MCG/2, FlexBus = MCG/2, Flash clock= MCG set_sys_dividers(0,1,1,3);
// Set the VCO divider and enable the PLL for 100MHz, LOLIE=0, PLLS= MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(26); //VDIV = 26 (x50) pll_freq = 100; break;
led, clk monitor disabled, PLL VCO divider is clear
ng option
1, CME=0, VDIV=1
60. 61. 62. 63. 64.
1, CME=0, VDIV=26
65. 66. 67.
/4
case 2:
// Set system options dividers
//MCG=PLL, core = MCG, bus = MCG/2, FlexBus = MCG/2, Flash clock= MCG set_sys_dividers(0,1,1,3);
// Set the VCO divider and enable the PLL for 96MHz, LOLIE=0, PLLS= MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(24); //VDIV = 24 (x48) pll_freq = 96; break; case 3:
// Set system options dividers
//MCG=PLL, core = MCG, bus = MCG, FlexBus = MCG, Flash clock= MCG/2 set_sys_dividers(0,0,0,1);
// Set the VCO divider and enable the PLL for 48MHz, LOLIE=0, PLLS= MCG_C6 = MCG_C6_PLLS_MASK; //VDIV = 0 (x24) pll_freq = 48; break; }
while (!(MCG_S & MCG_S_PLLST_MASK)){}; // wait for PLL status bit to set
68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98.
1, CME=0, VDIV=24
1, CME=0, VDIV=0
while (!(MCG_S & MCG_S_LOCK_MASK)){}; // Wait for LOCK bit to set
// Now running PBE Mode
// Transition into PEE by setting CLKS to 0 // CLKS=0, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0 MCG_C1 &= ~MCG_C1_CLKS_MASK;
// Wait for clock status bits to update
while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3){};
// Now running PEE Mode
return pll_freq; } //pll_init
这个函数中两个参数clk_option和crystal_val是两个枚举变量(enum),从它们的定义来看它们的取值范围是0~3和0~15.所以函数开始先进行有效性判断。
MCG表示的是 Multipurpose Clock Generator(多用途时钟发生器).MCG模块向MCU提供几个时钟源选择。这个模块包含了一
个 frequency-locked loop (FLL)和一个 phase-locked loop (PLL).FLL可以通过
内部的或外部的参考时钟源来控制,PLL可以通过外部参考时钟来控制。模块可以选择FLL或PLL的输出时钟或者内部或外部时钟源作为MCU的系统时钟。上面MCG_2指的是 MCG Control 2 Register. MCG一共有9种操作模式:FEI, FEE, FBI, FBE, PBE, PEE, BLPI,BLPE,and Stop. 不同运行模式的功耗互不相同,要进入各个模式需要写MCG_1~MCG_6寄存器组中某几个寄存器中的某几个位。 我们可以这样说,采用内部组件的模式所消耗的功率少于采用外部组件的模式。而MCG包括两种专门为低功率应用设计的模式——旁通低功耗内部(BLPI)和旁通低功耗外部(BLPE)。驱动BLPI模式的总线频率要比BLPE 模式低,因此BLPI 模式消耗的功率最小。下图2总结了每一种运行模式的功耗。
在sysinit()函数中对pll_init(unsigned char,unsigned char)函数的引用包含两个参数:CORE_CLK_MHZ和REF_CLK,从其定义可以看出其值分别为PLL96和XTAL8,分别代表2和3.K60_CLK 被定义为1.因此,在引用pll_init(unsigned char,unsigned char)函数时根据条件编译,执行的语句依次是: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.
// First move to FBE mode MCG_C2 = 0;
// after initialization of oscillator release latched state of oscillato
r and GPIO
SIM_SCGC4 |= SIM_SCGC4_LLWU_MASK; LLWU_CS |= LLWU_CS_ACKISO_MASK;
// Select external oscilator and Reference Divider and clear IREFS to start
ext osc
// CLKS=2, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0 MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3);
// wait for Reference clock Status bit to clear while (MCG_S & MCG_S_IREFST_MASK){};
// Wait for clock status bits to show clock source is ext ref clk while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2){};
MCG_C5 = MCG_C5_PRDIV(0x18);
/* Ensure MCG_C6 is at the reset default of 0. LOLIE disabled, PLL disable MCG_C6 = 0x0;
d, clk monitor disabled, PLL VCO divider is clear*/
23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45.
// Set system options dividers
//MCG=PLL, core = MCG, bus = MCG/2, FlexBus = MCG/2, Flash clock= MCG/4 set_sys_dividers(0,1,1,3);
// Set the VCO divider and enable the PLL for 96MHz, LOLIE=0, PLLS=1, CME= MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(24); //VDIV = 24 (x48) pll_freq = 96;
0, VDIV=24
while (!(MCG_S & MCG_S_PLLST_MASK)){}; // wait for PLL status bit to set
while (!(MCG_S & MCG_S_LOCK_MASK)){}; // Wait for LOCK bit to set
// Now running PBE Mode
// Transition into PEE by setting CLKS to 0 // CLKS=0, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0 MCG_C1 &= ~MCG_C1_CLKS_MASK;
// Wait for clock status bits to update
while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3){};
// Now running PEE Mode
return pll_freq;
最后,系统运行在PEE模式下。