?? sysinit.c
字號:
//-------------------------------------------------------------------------*
// 文件名:sysinit.c *
// 說 明: 系統配置文件 *
//-------------------------------------------------------------------------*
#include "sysinit.h" //頭文件
//全局變量聲明
int core_clk_khz;
int core_clk_mhz;
int periph_clk_khz;
//-------------------------------------------------------------------------*
//函數名: sysinit *
//功 能: 系統設置 *
//參 數: 無 *
//返 回: 無 *
//說 明: 無 *
//-------------------------------------------------------------------------*
void sysinit (void)
{
//使能IO端口時鐘
SIM_SCGC5 |= (SIM_SCGC5_PORTA_MASK
| SIM_SCGC5_PORTB_MASK
| SIM_SCGC5_PORTC_MASK
| SIM_SCGC5_PORTD_MASK
| SIM_SCGC5_PORTE_MASK );
//開啟系統時鐘
core_clk_mhz = pll_init(CORE_CLK_MHZ, REF_CLK);
//通過pll_init函數的返回值來計算內核時鐘和外設時鐘
core_clk_khz = core_clk_mhz * 1000;
periph_clk_khz = core_clk_khz / (((SIM_CLKDIV1 & SIM_CLKDIV1_OUTDIV2_MASK) >> 24)+ 1);
//使能跟蹤時鐘,用于調試
trace_clk_init();
//FlexBus時鐘初始化
fb_clk_init();
}
//-------------------------------------------------------------------------*
//函數名: trace_clk_init *
//功 能: 跟蹤時鐘初始化 *
//參 數: 無 *
//返 回: 無 *
//說 明: 用于調試 *
//-------------------------------------------------------------------------*
void trace_clk_init(void)
{
//設置跟蹤時鐘為內核時鐘
SIM_SOPT2 |= SIM_SOPT2_TRACECLKSEL_MASK;
//在PTA6引腳上使能TRACE_CLKOU功能
PORTA_PCR6 = ( PORT_PCR_MUX(0x7));
}
//-------------------------------------------------------------------------*
//函數名: fb_clk_init *
//功 能: FlexBus時鐘初始化 *
//參 數: 無 *
//返 回: 無 *
//說 明: *
//-------------------------------------------------------------------------*
void fb_clk_init(void)
{
//使能FlexBus模塊時鐘
SIM_SCGC7 |= SIM_SCGC7_FLEXBUS_MASK;
//在PTA6引腳上使能FB_CLKOUT功能
PORTC_PCR3 = ( PORT_PCR_MUX(0x5));
}
//-------------------------------------------------------------------------*
//函數名: pll_init *
//功 能: pll初始化 *
//參 數: clk_option:時鐘選項 *
// crystal_val:時鐘值 *
//返 回: 時鐘頻率值 *
//說 明: *
//-------------------------------------------------------------------------*
unsigned char pll_init(unsigned char clk_option, unsigned char crystal_val)
{
unsigned char pll_freq;
if (clk_option > 3) {return 0;} //如果沒有選擇可用的選項則返回0
if (crystal_val > 15) {return 1;} // 如果如果可用的晶體選項不可用則返回1
//這里處在默認的FEI模式
//首先移動到FBE模式
#if (defined(K60_CLK) || defined(ASB817))
MCG_C2 = 0;
#else
//使能外部晶振
MCG_C2 = MCG_C2_RANGE(2) | MCG_C2_HGO_MASK | MCG_C2_EREFS_MASK;
#endif
//初始化晶振后釋放鎖定狀態的振蕩器和GPIO
SIM_SCGC4 |= SIM_SCGC4_LLWU_MASK;
LLWU_CS |= LLWU_CS_ACKISO_MASK;
//選擇外部晶振,參考分頻器,清IREFS來啟動外部晶振
MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3);
//等待晶振穩定
#if (!defined(K60_CLK) && !defined(ASB817))
while (!(MCG_S & MCG_S_OSCINIT_MASK)){};
#endif
//等待參考時鐘狀態位清零
while (MCG_S & MCG_S_IREFST_MASK){};
//等待時鐘狀態位顯示時鐘源來自外部參考時鐘
while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2){};
//進入FBE模式
#if (defined(K60_CLK))
MCG_C5 = MCG_C5_PRDIV(0x18);
#else
//配置PLL分頻器來匹配所用的晶振
MCG_C5 = MCG_C5_PRDIV(crystal_val);
#endif
//確保MCG_C6處于復位狀態,禁止LOLIE、PLL、和時鐘控制器,清PLL VCO分頻器
MCG_C6 = 0x0;
//選擇PLL VCO分頻器,系統時鐘分頻器取決于時鐘選項
switch (clk_option) {
case 0:
//設置系統分頻器
//MCG=PLL, core = MCG, bus = MCG, FlexBus = MCG, Flash clock= MCG/2
set_sys_dividers(0,0,0,1);
//設置VCO分頻器,使能PLL為50MHz, LOLIE=0, PLLS=1, CME=0, VDIV=1
MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(1); //VDIV = 1 (x25)
pll_freq = 50;
break;
case 1:
//設置系統分頻器
//MCG=PLL, core = MCG, bus = MCG/2, FlexBus = MCG/2, Flash clock= MCG/4
set_sys_dividers(0,1,1,3);
//設置VCO分頻器,使能PLL為100MHz, LOLIE=0, PLLS=1, CME=0, VDIV=26
MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(26); //VDIV = 26 (x50)
pll_freq = 100;
break;
case 2:
//設置系統分頻器
//MCG=PLL, core = MCG, bus = MCG/2, FlexBus = MCG/2, Flash clock= MCG/4
set_sys_dividers(0,1,1,3);
//設置VCO分頻器,使能PLL為96MHz, LOLIE=0, PLLS=1, CME=0, VDIV=24
MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(24); //VDIV = 24 (x48)
pll_freq = 96;
break;
case 3:
//設置系統分頻器
//MCG=PLL, core = MCG, bus = MCG, FlexBus = MCG, Flash clock= MCG/2
set_sys_dividers(0,0,0,1);
//設置VCO分頻器,使能PLL為48MHz, LOLIE=0, PLLS=1, CME=0, VDIV=0
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
while (!(MCG_S & MCG_S_LOCK_MASK)){}; // Wait for LOCK bit to set
//進入PBE模式
//通過清零CLKS位來進入PEE模式
// CLKS=0, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0
MCG_C1 &= ~MCG_C1_CLKS_MASK;
//等待時鐘狀態位更新
while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3){};
//開始進入PEE模式
return pll_freq;
}
//-------------------------------------------------------------------------*
//函數名: set_sys_dividers *
//功 能: 設置系系統分頻器 *
//參 數: 預分頻值 *
//返 回: 無 *
//說 明: 此函數必須放在RAM里執行,否則會產生錯誤e2448。當FLASH時鐘分頻改變*
// 時,必須禁止FLASH的預取功能。在時鐘分頻改變之后,必須延時一小段時*
// 間才可以從新使能預取功能。 *
//-------------------------------------------------------------------------*
__ramfunc void set_sys_dividers(uint32 outdiv1, uint32 outdiv2, uint32 outdiv3, uint32 outdiv4)
{
uint32 temp_reg;
uint8 i;
//保存FMC_PFAPR當前的值
temp_reg = FMC_PFAPR;
//通過M&PFD置位M0PFD來禁止預取功能
FMC_PFAPR |= FMC_PFAPR_M7PFD_MASK | FMC_PFAPR_M6PFD_MASK | FMC_PFAPR_M5PFD_MASK
| FMC_PFAPR_M4PFD_MASK | FMC_PFAPR_M3PFD_MASK | FMC_PFAPR_M2PFD_MASK
| FMC_PFAPR_M1PFD_MASK | FMC_PFAPR_M0PFD_MASK;
//給時鐘分頻器設置期望值
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(outdiv1) | SIM_CLKDIV1_OUTDIV2(outdiv2)
| SIM_CLKDIV1_OUTDIV3(outdiv3) | SIM_CLKDIV1_OUTDIV4(outdiv4);
//等待分頻器改變
for (i = 0 ; i < outdiv4 ; i++)
{}
//從新存FMC_PFAPR的原始值
FMC_PFAPR = temp_reg;
return;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -