S32K144之時鍾配置


 

一般來說,時鍾精度、穩定性取決於所采用的時鍾源,就MCU S32K來說如內部振盪器SIRC,FIRC,128KLPO,外部晶振等,跟所使用的外設(FTM, LPIT,LPT,RTC等)和哪一路輸出時鍾(SYS_CLK,BUS_CLK,SPLLDVI1_CLK等)沒有直接關系。

由於S32K144提供的時鍾源和配置方法比較多,那么如何有效配置得到自己想要的時鍾呢?
下面以S32K144為例,從時鍾定義圖開始,逐步介紹如何尋找S32K144時鍾(CORE_CLK, BUS_CLK,)合適的配置方法,並根據測試方法驗證配置是否有效。

 

0. 目標
輸出目標
clock clock= 80MHz(以下MHz簡稱M)
bus clock=40MHz, Normal Mode(默認)
 注意:只有支持105℃的部分S32K144型號,core clock才能支持到最高112M(HSRUN),其他型號不論HSRUN模式,還是RUN模式,最高支持80M。
 
測試工具
PCB: S32K144EVB-Q100
IDE: S32DS for ARM 2018.R1 
 

1.時鍾定義

配置時鍾先從學會看時鍾分配圖開始,會看圖了,配置就成功了一半。

 
因為能實現目標的路徑可能有多種,這里先選中一條配置路徑,再判斷是否可行(藍色箭頭+框)。
時鍾源選擇外部晶振8M,即SOSC=8M => SPLL時鍾源 SPLL_CLK_SOURCE = SOSC = 8M,

 

  2.確認內部時鍾要求

CORE_CLK/ SYS_CLK 最高支持112M(HSRUN) , 80M(RUN),目標@80M符合要求。

不過,BUS_CLK最高支持56M(HSRUN), 48M(RUN),目標@40M符合要求。

3.確認外部晶振 8M

查看S32KEVB-Q100評估板原理圖,知外部晶振8M => System PLL輸入 SPLL_SOURCE=8M 

 
 
4.確認System PLL分頻及倍頻
這里選擇PREDIV=0, MULT=0b11000 (10進制: 24) 
VCO_CLK=8M/(0+1) X (24+16) = 320MHz
SPLL_CLK=(VCO_CLK)/2 = 160MHz
 

 

 

考慮:這里MULTI還可以>24 => 倍頻因子>40,那么能不能配置VCO_CLK >320M,而最終CORE_CLK=80M呢?

答案是不行,因為VCO_CLK最高支持到320M,可以參考S32K-RM。

 

 5.具體寄存器配置

可參考RM配置方法

 

6.設置檢測方法

1)初步確定為通過IO口直接輸出與總線時鍾相關的時鍾或者分頻后的時鍾
2)尋找SCH上是否有可直接利用的MCU引腳
MCU完整型號:FS32K144HRT0VLLT, 封裝:LQFP100
查RM附件IO描述表,發現能作為CLKOUT pin的有PTD14, PTE10, PTB5。
 
如有可用CLKOUT pin,配置相應的pin為CLKOUT功能
1)配置PORT的MUX為CLKOUT對應ALT功能,並使能端口時鍾;
 
2)配置SIM_CHIPCTL選擇輸出的時鍾,以及輸出的分頻系數;
輸出時鍾結構
 
 
CLKOUTSEL - 選擇輸出時鍾,如選擇設置CLKOUTSEL=0b1001,則CLKOUT pin輸出Bus_Clock
 
7.時鍾配置代碼
main.c
int main(void)
{
        volatile uint32_t cnt = 0;

    Clock_Init();

    Port_Init();

    Clock_Out_Bus();

    while(1)
    {
        cnt ++;
    }

    return 0;
}
View Code

 

clock.c - 時鍾配置

/**
 * 配置MCU時鍾, 使SYS_CLK=80MHz, BUS_CLK=40MHz, FLASH_CLK=20MHz, 用外部晶振f_osc=8MHz
 * SPLL_CLK=160MHz, VCO_CLK=320MHz
 * @note
 * 計算公式:
 * BUS_CLK=SYS_CLK / DIVBUS
 * SYS_CLK=SPLL_CLK / DIVCORE
 * SPLL_CLK=(VCO_CLK) / 2
 * VCO_CLK=SPLL_SOURCE / (PREDIV + 1) x (MULT + 16)
 * 選擇外部晶振作為SPLL_SOURCE, SPLL_SOURCE=8MHz
 */
void Clock_Init(void)
{
    // 以下初始化順序不可改變

    Clock_SOSC_Init_8M(); // SOSC&SPLL_SOURCE初始化為輸出8M

    Clock_SPLL_Init_160M(); // SPLL&SCG初始化為輸出160M

    Clock_RUNMode_SYS_Init_80M(); // sys clock = 80M, bus clock = 40M, flash = 20M

}


void Clock_ConfigureOut(SIM_CLKOUTSEL_Type clkoutsel)
{
    if(clkoutsel <= RTC_CLK)
    {
        SIM->CHIPCTL &= ~SIM_CHIPCTL_CLKOUTEN_MASK; // disable CLKOUT
        SIM->CHIPCTL &= ~SIM_CHIPCTL_CLKOUTSEL_MASK; // clear CLKOUT

        SIM->CHIPCTL |= SIM_CHIPCTL_CLKOUTSEL(clkoutsel); // select CLKOUT source = clkoutsel

        SIM->CHIPCTL |= SIM_CHIPCTL_CLKOUTEN_MASK; // enable CLKOUT
    }
}


/**
 * CLKOUT pin輸出Bus CLK
 */
void Clock_Out_Bus(void)
{
    Clock_ConfigureOut(BUS_CLK);
}

/**
 * 配置SOSC_CLK=8M
 * @output SOSCDIV1_CLK
 * @output SOSCDIV2_CLK
 * @note
 * 外部晶振8M
 * 計算公式
 * SOSCDIV1_CLK=SOSC_CLK / SOSCDIV1
 * SOSCDIV2_CLK=SOSC_CLK / SOSCDIV2
 */
void Clock_SOSC_Init_8M(void)
{
    // Frequency division for SOSCDIV1_CLK, SOSCDIV2_CLK
    SCG->SOSCDIV=SCG_SOSCDIV_SOSCDIV1(1) // SOSCDIV1=1 : Divide by 1
            | SCG_SOSCDIV_SOSCDIV2(1);   // SOSCDIV2=1 : Divide by 1

    SCG->SOSCCFG=SCG_SOSCCFG_RANGE(0b11) // RANGE=3: 8-40 MHz SOSC
            // RANGE=3: 8-40 MHz SOSC
            | SCG_SOSCCFG_HGO(1)    // HGO=0: Configure crystal oscillator for high-gain operation
            | SCG_SOSCCFG_EREFS(1); // EREFS=1: Internal crystal oscillator of OSC selected

    while(SCG->SOSCCSR & SCG_SOSCCSR_LK_MASK); /* Ensure SOSCCSR unlocked */
    SCG->SOSCCSR = SCG_SOSCCSR_SOSCEN(1);      // SOSC Enable
}

/**
 * 配置MCU時鍾SPLL_CLK=160M
 * @require SOSC_CLK = 8M
 * @output SPLL_CLK
 */
void Clock_SPLL_Init_160M(void)
{
    while(SCG->SPLLCSR & SCG_SPLLCSR_LK_MASK); /* Ensure SPLLCSR unlocked */

    // 關閉SPLL
    SCG->SPLLCSR = 0; /* SPLLEN=0: SPLL is disabled (default) */

    // 配置SCG_SPLLCFG, 使VCO_CLK=320MHz, SPLL_CLK=160MHz
    SCG->SPLLCFG = SCG_SPLLCFG_PREDIV(0) | SCG_SPLLCFG_MULT(0b11000);

    SCG->RCCR = SCG_RCCR_SCS(0b0110)  // System Clock Source: System PLL (SPLL_CLK)
            | SCG_RCCR_DIVCORE(0)   // DIVCORE=0
            | SCG_RCCR_DIVBUS(1)    // DIVBUS=1
            | SCG_RCCR_DIVSLOW(1);  // DVISLOW=1

    // 使能SPLL
    SCG->SPLLCSR |= SCG_SPLLCSR_SPLLEN_MASK;
    // Lock SPLL
    SCG->SPLLCSR |= SCG_SPLLCSR_LK_MASK;
}


/**
 * SYS_CLK = 80M, BUS_CLK = 40M, FLASH_CLK=20M
 * @require SPLL_CLK=160M
 * @note SYS_CLK=80MHz,BUS_CLK=40MHz, 使用外部晶振f_osc=8MHz
 * 前提條件使用SPLL_SOURCE=160M作為system clock
 * 計算公式:
 * SYS_CLK=SPLL_CLK / DIVCORE
 * BUS_CLK=SYS_CLK / DIVBUS
 * FLASH_CLK=SYS_CLK / DIVSLOW
 * SPLL_CLK=(VCO_CLK) / 2
 * VCO_CLK=SPLL_SOURCE / (PREDIV + 1) x (MULT + 16)
 *
 * =>DIVCORE=1, DIVBUS=1,DIVSLOW=3
 */
void Clock_RUNMode_SYS_Init_80M(void)
{
    // 配置system clock源, DIVCORE, DIVBUS, DIVFLASH
    SCG->RCCR = SCG_RCCR_SCS(0b0110)// Select System Clock Source: System PLL (SPLL_CLK)
            | SCG_RCCR_DIVCORE(1)
            | SCG_RCCR_DIVBUS(1)
            | SCG_RCCR_DIVSLOW(3);

    // 檢查Clock Status(SCG_CSR) 是否為RCCR配置
    while(0b0110 != (SCG->CSR & SCG_CSR_SCS_MASK) >> SCG_CSR_SCS_SHIFT) { }
}
View Code

 

Port.c
#define PORTD14_IDX              14
#define PORTD16_IDX              16

#define PORT_CLKOUT_IDX          PORTD14_IDX
#define PORT_LED_GREEN_IDX       PORTD16_IDX


/*
 * PTD14 - CLKOUT
 * PTD16 - GPO for LED
 */
void Port_Init(void)
{
    // Enable clock to PORTD
    if(PCC->PCCn[PCC_PORTD_INDEX] & PCC_PCCn_PR_MASK)
    {
        PCC->PCCn[PCC_PORTD_INDEX] |= PCC_PCCn_CGC(1); // Clock enabled to PORTD
    }

    // Set Port Data Direction
    PTD->PDDR |= 1 << PORT_LED_GREEN_IDX; // Port Data Direction: output

    // set/clear PortD's value
//    PTD->PTSO |= 1 << PORT_LED_GREEN_IDX; // Port Set Output
    PTD->PCOR |= 1 << PORT_LED_GREEN_IDX; // Port Clear Output


    // PTD16 - GPO
    PORTD->PCR[PORT_LED_GREEN_IDX] = PORT_PCR_MUX(0b0000001); // Port D16: MUX=ALT1, GPIO(to green LED on EVB/PCB)
    // PTD14 - CLKOUT
    PORTD->PCR[PORT_CLKOUT_IDX] = PORT_PCR_MUX(0b00000111);  // Port D14: MUX=ALT4, CLKOUT

}
View Code

 

clock.c - CLKOUT 輸出選擇

/**
 * CLKOUT pin輸出Bus CLK
 */
void Clock_Out_Bus(void)
{
    Clock_ConfigureOut(0b1001);
}


void Clock_ConfigureOut(SIM_CLKOUTSEL_Type clkoutsel)
{
    if(clkoutsel <= 0b1110)
    {
        SIM->CHIPCTL &= ~SIM_CHIPCTL_CLKOUTEN_MASK; // disable CLKOUT
        SIM->CHIPCTL &= ~SIM_CHIPCTL_CLKOUTSEL_MASK; // clear CLKOUT

        SIM->CHIPCTL |= SIM_CHIPCTL_CLKOUTSEL(clkoutsel); // select CLKOUT source = clkoutsel

        SIM->CHIPCTL |= SIM_CHIPCTL_CLKOUTEN_MASK; // enable CLKOUT
    }
}
View Code

 

8. 觀察CLKPUT pin 輸出

需要用示波器觀測PTD14,截圖略。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM