亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

Chinaunix

標題: 【學習筆記】IAR中cortex-m4啟動流程分析(2) [打印本頁]

作者: houxn22    時間: 2011-12-21 08:41
標題: 【學習筆記】IAR中cortex-m4啟動流程分析(2)
    上次寫了飛思卡爾官方給出的demo程序的啟動流程的前面部分:
    在存儲器最前面放置好向量表-->把通用寄存器清零-->開中斷-->跳轉(zhuǎn)到start函數(shù)繼續(xù)執(zhí)行初始化。在start函數(shù)中,順次執(zhí)行三個函數(shù):禁用看門狗-->初始化C語言環(huán)境(向量表重定向、拷貝數(shù)據(jù)段到RAM、清零bss段等)-->系統(tǒng)外設初始化。
③系統(tǒng)外設初始化函數(shù) sysinit()
  1. #include "common.h"
  2. #include "sysinit.h"
  3. #include "uart.h"

  4. /********************************************************************/

  5. /* Actual system clock frequency */
  6. int core_clk_khz;
  7. int core_clk_mhz;
  8. int periph_clk_khz;

  9. /********************************************************************/
  10. void sysinit (void)
  11. {
  12.         /*
  13.          * Enable all of the port clocks. These have to be enabled to configure
  14.          * pin muxing options, so most code will need all of these on anyway.
  15.          */
  16.         SIM_SCGC5 |= (SIM_SCGC5_PORTA_MASK
  17.                       | SIM_SCGC5_PORTB_MASK
  18.                       | SIM_SCGC5_PORTC_MASK
  19.                       | SIM_SCGC5_PORTD_MASK
  20.                       | SIM_SCGC5_PORTE_MASK );

  21.      /* Ramp up the system clock */
  22.     core_clk_mhz = pll_init(CORE_CLK_MHZ, REF_CLK);

  23.     /*
  24.          * Use the value obtained from the pll_init function to define variables
  25.      * for the core clock in kHz and also the peripheral clock. These
  26.      * variables can be used by other functions that need awareness of the
  27.      * system frequency.
  28.      */
  29.     core_clk_khz = core_clk_mhz * 1000;
  30.       periph_clk_khz = core_clk_khz / (((SIM_CLKDIV1 & SIM_CLKDIV1_OUTDIV2_MASK) >> 24)+ 1);

  31.       /* For debugging purposes, enable the trace clock and/or FB_CLK so that
  32.        * we'll be able to monitor clocks and know the PLL is at the frequency
  33.        * that we expect.
  34.        */
  35.     trace_clk_init();
  36.       fb_clk_init();

  37.       /* Enable the pins for the selected UART */
  38.          if (TERM_PORT == UART0_BASE_PTR)
  39.          {
  40.             /* Enable the UART0_TXD function on PTD6 */
  41.             PORTD_PCR6 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

  42.             /* Enable the UART0_RXD function on PTD7 */
  43.             PORTD_PCR7 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
  44.          }

  45.          if (TERM_PORT == UART1_BASE_PTR)
  46.        {
  47.                  /* Enable the UART1_TXD function on PTC4 */
  48.           PORTC_PCR4 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

  49.           /* Enable the UART1_RXD function on PTC3 */
  50.           PORTC_PCR3 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
  51.       }

  52.       if (TERM_PORT == UART2_BASE_PTR)
  53.       {
  54.                  /* Enable the UART2_TXD function on PTD3 */
  55.           PORTD_PCR3 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

  56.           /* Enable the UART2_RXD function on PTD2 */
  57.           PORTD_PCR2 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
  58.       }

  59.       if (TERM_PORT == UART3_BASE_PTR)
  60.       {
  61.                  /* Enable the UART3_TXD function on PTC17 */
  62.           PORTC_PCR17 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

  63.           /* Enable the UART3_RXD function on PTC16 */
  64.           PORTC_PCR16 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
  65.       }
  66.       if (TERM_PORT == UART4_BASE_PTR)
  67.       {
  68.                  /* Enable the UART3_TXD function on PTC17 */
  69.           PORTE_PCR24 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

  70.           /* Enable the UART3_RXD function on PTC16 */
  71.           PORTE_PCR25 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
  72.       }
  73.       if (TERM_PORT == UART5_BASE_PTR)
  74.       {
  75.                  /* Enable the UART3_TXD function on PTC17 */
  76.           PORTE_PCR8 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin

  77.           /* Enable the UART3_RXD function on PTC16 */
  78.           PORTE_PCR9 = PORT_PCR_MUX(0x3); // UART is alt3 function for this pin
  79.       }
  80.       /* UART0 and UART1 are clocked from the core clock, but all other UARTs are
  81.          * clocked from the peripheral clock. So we have to determine which clock
  82.          * to send to the uart_init function.
  83.          */
  84.         if ((TERM_PORT == UART0_BASE_PTR) | (TERM_PORT == UART1_BASE_PTR))
  85.             uart_init (TERM_PORT, core_clk_khz, TERMINAL_BAUD);
  86.         else
  87.        uart_init (TERM_PORT, periph_clk_khz, TERMINAL_BAUD);
  88. }
  89. /********************************************************************/
  90. void trace_clk_init(void)
  91. {
  92.     /* Set the trace clock to the core clock frequency */
  93.     SIM_SOPT2 |= SIM_SOPT2_TRACECLKSEL_MASK;

  94.     /* Enable the TRACE_CLKOUT pin function on PTA6 (alt7 function) */
  95.     PORTA_PCR6 = ( PORT_PCR_MUX(0x7));
  96. }
  97. /********************************************************************/
  98. void fb_clk_init(void)
  99. {
  100.     /* Enable the clock to the FlexBus module */
  101.         SIM_SCGC7 |= SIM_SCGC7_FLEXBUS_MASK;

  102.      /* Enable the FB_CLKOUT function on PTC3 (alt5 function) */
  103.     PORTC_PCR3 = ( PORT_PCR_MUX(0x5));
  104. }
  105. /********************************************************************/
首先寫SIM_SCGC5寄存器。SCGC5表示的是System Clock Gating Control Register 5(系統(tǒng)時鐘門控制寄存器5).系統(tǒng)集成模塊 --System integration module (SIM)--控制寄存器組中共有8個SCGC寄存器,它們分別控制不同外設所需要的時鐘的開關(guān),SCGC5寄存器控制的是PORTA~PORTE、TSI、REGFILE和LPTIMER時鐘的開關(guān),向?qū)奈粚懭?表示使能時鐘。第一段代碼分別打開了PORTA~PORTE的時鐘開關(guān)。
上面pll_init(unsigned char,unsigned char)函數(shù)用來增加系統(tǒng)時鐘。
  1. unsigned char pll_init(unsigned char clk_option, unsigned char crystal_val)
  2. {
  3.   unsigned char pll_freq;

  4.   if (clk_option > 3) {return 0;} //return 0 if one of the available options is not selected
  5.   if (crystal_val > 15) {return 1;} // return 1 if one of the available crystal options is not available
  6. //This assumes that the MCG is in default FEI mode out of reset.

  7. // First move to FBE mode
  8. #if (defined(K60_CLK) || defined(ASB817))
  9.      MCG_C2 = 0;
  10. #else
  11. // Enable external oscillator, RANGE=2, HGO=1, EREFS=1, LP=0, IRCS=0
  12.     MCG_C2 = MCG_C2_RANGE(2) | MCG_C2_HGO_MASK | MCG_C2_EREFS_MASK;
  13. #endif

  14. // after initialization of oscillator release latched state of oscillator and GPIO
  15.     SIM_SCGC4 |= SIM_SCGC4_LLWU_MASK;
  16.     LLWU_CS |= LLWU_CS_ACKISO_MASK;
  17.   
  18. // Select external oscilator and Reference Divider and clear IREFS to start ext osc
  19. // CLKS=2, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0
  20.   MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3);

  21.   /* if we aren't using an osc input we don't need to wait for the osc to init */
  22. #if (!defined(K60_CLK) && !defined(ASB817))
  23.     while (!(MCG_S & MCG_S_OSCINIT_MASK)){}; // wait for oscillator to initialize
  24. #endif

  25.   while (MCG_S & MCG_S_IREFST_MASK){}; // wait for Reference clock Status bit to clear

  26.   while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2){}; // Wait for clock status bits to show clock source is ext ref clk

  27. // Now in FBE

  28. #if (defined(K60_CLK))
  29.    MCG_C5 = MCG_C5_PRDIV(0x18);
  30. #else
  31. // Configure PLL Ref Divider, PLLCLKEN=0, PLLSTEN=0, PRDIV=5
  32. // The crystal frequency is used to select the PRDIV value. Only even frequency crystals are supported
  33. // that will produce a 2MHz reference clock to the PLL.
  34.   MCG_C5 = MCG_C5_PRDIV(crystal_val); // Set PLL ref divider to match the crystal used
  35. #endif

  36.   // Ensure MCG_C6 is at the reset default of 0. LOLIE disabled, PLL disabled, clk monitor disabled, PLL VCO divider is clear
  37.   MCG_C6 = 0x0;
  38. // Select the PLL VCO divider and system clock dividers depending on clocking option
  39.   switch (clk_option) {
  40.     case 0:
  41.       // Set system options dividers
  42.       //MCG=PLL, core = MCG, bus = MCG, FlexBus = MCG, Flash clock= MCG/2
  43.       set_sys_dividers(0,0,0,1);
  44.       // Set the VCO divider and enable the PLL for 50MHz, LOLIE=0, PLLS=1, CME=0, VDIV=1
  45.       MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(1); //VDIV = 1 (x25)
  46.       pll_freq = 50;
  47.       break;
  48.    case 1:
  49.       // Set system options dividers
  50.       //MCG=PLL, core = MCG, bus = MCG/2, FlexBus = MCG/2, Flash clock= MCG/4
  51.      set_sys_dividers(0,1,1,3);
  52.       // Set the VCO divider and enable the PLL for 100MHz, LOLIE=0, PLLS=1, CME=0, VDIV=26
  53.       MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(26); //VDIV = 26 (x50)
  54.       pll_freq = 100;
  55.       break;
  56.     case 2:
  57.       // Set system options dividers
  58.       //MCG=PLL, core = MCG, bus = MCG/2, FlexBus = MCG/2, Flash clock= MCG/4
  59.       set_sys_dividers(0,1,1,3);
  60.       // Set the VCO divider and enable the PLL for 96MHz, LOLIE=0, PLLS=1, CME=0, VDIV=24
  61.       MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(24); //VDIV = 24 (x48)
  62.       pll_freq = 96;
  63.       break;
  64.    case 3:
  65.       // Set system options dividers
  66.       //MCG=PLL, core = MCG, bus = MCG, FlexBus = MCG, Flash clock= MCG/2
  67.       set_sys_dividers(0,0,0,1);
  68.       // Set the VCO divider and enable the PLL for 48MHz, LOLIE=0, PLLS=1, CME=0, VDIV=0
  69.       MCG_C6 = MCG_C6_PLLS_MASK; //VDIV = 0 (x24)
  70.       pll_freq = 48;
  71.       break;
  72.   }
  73.   while (!(MCG_S & MCG_S_PLLST_MASK)){}; // wait for PLL status bit to set

  74.   while (!(MCG_S & MCG_S_LOCK_MASK)){}; // Wait for LOCK bit to set

  75. // Now running PBE Mode

  76. // Transition into PEE by setting CLKS to 0
  77. // CLKS=0, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0
  78.   MCG_C1 &= ~MCG_C1_CLKS_MASK;

  79. // Wait for clock status bits to update
  80.   while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3){};

  81. // Now running PEE Mode

  82. return pll_freq;
  83. } //pll_init
    這個函數(shù)中兩個參數(shù)clk_option和crystal_val是兩個枚舉變量(enum),從它們的定義來看它們的取值范圍是0~3和0~15.所以函數(shù)開始先進行有效性判斷。
        MCG表示的是 Multipurpose Clock Generator(多用途時鐘發(fā)生器).MCG模塊向MCU提供幾個時鐘源選擇。這個模塊包含了一個 frequency-locked loop (FLL)和一個 phase-locked loop (PLL).FLL可以通過內(nèi)部的或外部的參考時鐘源來控制,PLL可以通過外部參考時鐘來控制。模塊可以選擇FLL或PLL的輸出時鐘或者內(nèi)部或外部時鐘源作為MCU的系統(tǒng)時鐘。上面MCG_2指的是 MCG Control 2 Register. MCG一共有9種操作模式:FEI, FEE, FBI, FBE, PBE, PEE, BLPI,BLPE,and Stop. 不同運行模式的功耗互不相同,要進入各個模式需要寫MCG_1~MCG_6寄存器組中某幾個寄存器中的某幾個位。  我們可以這樣說,采用內(nèi)部組件的模式所消耗的功率少于采用外部組件的模式。而MCG包括兩種專門為低功率應用設計的模式——旁通低功耗內(nèi)部(BLPI)和旁通低功耗外部(BLPE)。驅(qū)動BLPI模式的總線頻率要比BLPE 模式低,因此BLPI 模式消耗的功率最小。下圖2總結(jié)了每一種運行模式的功耗。

    在sysinit()函數(shù)中對pll_init(unsigned char,unsigned char)函數(shù)的引用包含兩個參數(shù):CORE_CLK_MHZ和REF_CLK,從其定義可以看出其值分別為PLL96和XTAL8,分別代表2和3.K60_CLK 被定義為1.因此,在引用pll_init(unsigned char,unsigned char)函數(shù)時根據(jù)條件編譯,執(zhí)行的語句依次是: 
  1. // First move to FBE mode
  2. MCG_C2 = 0;

  3. // after initialization of oscillator release latched state of oscillator and GPIO
  4.     SIM_SCGC4 |= SIM_SCGC4_LLWU_MASK;
  5.     LLWU_CS |= LLWU_CS_ACKISO_MASK;

  6. // Select external oscilator and Reference Divider and clear IREFS to start ext osc
  7. // CLKS=2, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0
  8.   MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3);

  9. // wait for Reference clock Status bit to clear
  10. while (MCG_S & MCG_S_IREFST_MASK){};

  11. // Wait for clock status bits to show clock source is ext ref clk
  12. while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2){};

  13. MCG_C5 = MCG_C5_PRDIV(0x18);

  14. /* Ensure MCG_C6 is at the reset default of 0. LOLIE disabled, PLL disabled, clk monitor disabled, PLL VCO divider is clear*/
  15.   MCG_C6 = 0x0;

  16. // Set system options dividers
  17. //MCG=PLL, core = MCG, bus = MCG/2, FlexBus = MCG/2, Flash clock= MCG/4
  18.    set_sys_dividers(0,1,1,3);
  19. // Set the VCO divider and enable the PLL for 96MHz, LOLIE=0, PLLS=1, CME=0, VDIV=24
  20.       MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(24); //VDIV = 24 (x48)
  21.       pll_freq = 96;

  22. while (!(MCG_S & MCG_S_PLLST_MASK)){}; // wait for PLL status bit to set

  23.   while (!(MCG_S & MCG_S_LOCK_MASK)){}; // Wait for LOCK bit to set

  24. // Now running PBE Mode

  25. // Transition into PEE by setting CLKS to 0
  26. // CLKS=0, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0
  27.   MCG_C1 &= ~MCG_C1_CLKS_MASK;

  28. // Wait for clock status bits to update
  29.   while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3){};

  30. // Now running PEE Mode

  31. return pll_freq;
    最后,系統(tǒng)運行在PEE模式下。





歡迎光臨 Chinaunix (http://www.72891.cn/) Powered by Discuz! X3.2