?? sysinit.c
字號:
//-------------------------------------------------------------------------*
// 文件名:sysinit.c *
// 說 明: 系統(tǒng)配置文件 *
//-------------------------------------------------------------------------*
#include "sysinit.h" //頭文件
//全局變量聲明
int core_clk_khz;
int core_clk_mhz;
int periph_clk_khz;
//-------------------------------------------------------------------------*
//函數(shù)名: sysinit *
//功 能: 系統(tǒng)設(shè)置 *
//參 數(shù): 無 *
//返 回: 無 *
//說 明: 無 *
//-------------------------------------------------------------------------*
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 );
//開啟系統(tǒng)時鐘
core_clk_mhz = pll_init(CORE_CLK_MHZ, REF_CLK);
//通過pll_init函數(shù)的返回值來計算內(nèi)核時鐘和外設(shè)時鐘
core_clk_khz = core_clk_mhz * 1000;
periph_clk_khz = core_clk_khz / (((SIM_CLKDIV1 & SIM_CLKDIV1_OUTDIV2_MASK) >> 24)+ 1);
//使能跟蹤時鐘,用于調(diào)試
trace_clk_init();
//FlexBus時鐘初始化
fb_clk_init();
}
//-------------------------------------------------------------------------*
//函數(shù)名: trace_clk_init *
//功 能: 跟蹤時鐘初始化 *
//參 數(shù): 無 *
//返 回: 無 *
//說 明: 用于調(diào)試 *
//-------------------------------------------------------------------------*
void trace_clk_init(void)
{
//設(shè)置跟蹤時鐘為內(nèi)核時鐘
SIM_SOPT2 |= SIM_SOPT2_TRACECLKSEL_MASK;
//在PTA6引腳上使能TRACE_CLKOU功能
PORTA_PCR6 = ( PORT_PCR_MUX(0x7));
}
//-------------------------------------------------------------------------*
//函數(shù)名: fb_clk_init *
//功 能: FlexBus時鐘初始化 *
//參 數(shù): 無 *
//返 回: 無 *
//說 明: *
//-------------------------------------------------------------------------*
void fb_clk_init(void)
{
//使能FlexBus模塊時鐘
SIM_SCGC7 |= SIM_SCGC7_FLEXBUS_MASK;
//在PTA6引腳上使能FB_CLKOUT功能
PORTC_PCR3 = ( PORT_PCR_MUX(0x5));
}
//-------------------------------------------------------------------------*
//函數(shù)名: pll_init *
//功 能: pll初始化 *
//參 數(shù): 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
//初始化晶振后釋放鎖定狀態(tài)的振蕩器和GPIO
SIM_SCGC4 |= SIM_SCGC4_LLWU_MASK;
LLWU_CS |= LLWU_CS_ACKISO_MASK;
//選擇外部晶振,參考分頻器,清IREFS來啟動外部晶振
MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3);
//等待晶振穩(wěn)定
#if (!defined(K60_CLK) && !defined(ASB817))
while (!(MCG_S & MCG_S_OSCINIT_MASK)){};
#endif
//等待參考時鐘狀態(tài)位清零,即指明FLL時鐘源來自外部
while (MCG_S & MCG_S_IREFST_MASK){};
//等待時鐘狀態(tài)位顯示時鐘源來自外部參考時鐘
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處于復(fù)位狀態(tài),禁止LOLIE、PLL、和時鐘控制器,清PLL VCO分頻器
MCG_C6 = 0x0;
//選擇PLL VCO分頻器,系統(tǒng)時鐘分頻器取決于時鐘選項
switch (clk_option) {
case 0:
//設(shè)置系統(tǒng)分頻器
//MCG=PLL, core = MCG, bus = MCG, FlexBus = MCG, Flash clock= MCG/2
set_sys_dividers(0,0,0,1);
//設(shè)置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:
//設(shè)置系統(tǒng)分頻器
//MCG=PLL, core = MCG, bus = MCG/2, FlexBus = MCG/2, Flash clock= MCG/4
set_sys_dividers(0,1,1,3);
//設(shè)置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:
//設(shè)置系統(tǒng)分頻器
//MCG=PLL, core = MCG, bus = MCG/2, FlexBus = MCG/2, Flash clock= MCG/4
set_sys_dividers(0,1,1,3);
//設(shè)置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:
//設(shè)置系統(tǒng)分頻器
//MCG=PLL, core = MCG, bus = MCG, FlexBus = MCG, Flash clock= MCG/2
set_sys_dividers(0,0,0,1);
//設(shè)置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;
//等待時鐘狀態(tài)位更新
while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3){};
//開始進入PEE模式
return pll_freq;
}
//-------------------------------------------------------------------------*
//函數(shù)名: set_sys_dividers *
//功 能: 設(shè)置系系統(tǒng)分頻器 *
//參 數(shù): 預(yù)分頻值 *
//返 回: 無 *
//說 明: 此函數(shù)必須放在RAM里執(zhí)行,否則會產(chǎn)生錯誤e2448。當FLASH時鐘分頻改變*
// 時,必須禁止FLASH的預(yù)取功能。在時鐘分頻改變之后,必須延時一小段時*
// 間才可以從新使能預(yù)取功能。 *
//-------------------------------------------------------------------------*
__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來禁止預(yù)取功能
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;
//給時鐘分頻器設(shè)置期望值
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;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -