Linux启动内核必要节点分析及时钟系统简述

Linux启动内核必要节点分析及时钟系统简述

前言

本文主要对设备树和时钟系统进行说明。

  • 设备树:主要由 cpus node 和 soc node 两部分组成。

    cpus node 对所使用的 cpu信息进行描述,架构、支持频率、时钟等。

    soc node 对板载的信息进行描述,晶振、内存、外设等等。

  • 时钟系统

    参考“IMX6ULL参考手册” 以IMX6ULL为例从时钟生成、时钟控制、时钟树到时钟选择/配置几方面进行描述。

1. 设备树

本次整理的设备树是基于精简后的IMX6ULL的设备树文件,只包含内核启动的必要元素。(设备树的组成、基本语法、匹配内核及搭建,查看 “ 设备树的组成及搭建.pdf ” )

1.1. cpus node

因为 imx6ull 是单核的,所以只有一个 cpu0 子节点,cpu0节点信息描述如下所示:

cpus {
    #address-cells = <1>;
    #size-cells = <0>;

	cpu0: cpu@0 {
        compatible = "arm,cortex-a7";	/* 架构信息 */
        device_type = "cpu";	
        reg = <0>;
        clock-latency = <61036>;	 /* 时钟延时:two CLK32 periods */
		/* 时钟延时(lantency)时钟从时钟源(例如晶振、PLL 或分频器输出端)出发到达触发器端口的延迟时
	    间,称为时钟延时。时钟延时包括时钟源延迟(source latency)和时钟网络延迟(network latency) */
        operating-points = <		/* 支持频率 */
            /* kHz	uV */
            996000	1275000
            792000	1225000
            528000	1175000
            396000	1025000
            198000	950000
        >;
        fsl,soc-operating-points = <
            /* KHz	uV */
            996000	1175000
            792000	1175000
            528000	1175000
            396000	1175000
            198000	1175000
        >;
        fsl,low-power-run;
        clocks = <&clks IMX6UL_CLK_ARM>,		/* 时钟 */
                <&clks IMX6UL_CLK_PLL2_BUS>,
                <&clks IMX6UL_CLK_PLL2_PFD2>,
                <&clks IMX6UL_CA7_SECONDARY_SEL>,
                <&clks IMX6UL_CLK_STEP>,
                <&clks IMX6UL_CLK_PLL1_SW>,
                <&clks IMX6UL_CLK_PLL1_SYS>,
                <&clks IMX6UL_PLL1_BYPASS>,
                <&clks IMX6UL_CLK_PLL1>,
                <&clks IMX6UL_PLL1_BYPASS_SRC>,
                <&clks IMX6UL_CLK_OSC>;
        clock-names = "arm", "pll2_bus",  "pll2_pfd2_396m", "secondary_sel", "step",
        "pll1_sw", "pll1_sys", "pll1_bypass", "pll1", "pll1_bypass_src", "osc";
    };
};

1.2. soc node

1.2.1 时钟源 - clocks

时钟源是固定参数,其他时钟都是经过时钟源进行分频/倍频得到的。设备树中时钟源的描述,如下:

clocks {
    #address-cells = <1>;
    #size-cells = <0>;
   
    ckil: clock@0 {		 /* 32.768KHZ晶振,RTC时钟源 */
        compatible = "fixed-clock";
        reg = <0>;
        #clock-cells = <0>;
        clock-frequency = <32768>;
        clock-output-names = "ckil";
    };

    osc: clock@1 {  	  /* 24MHZ的晶振 */
        compatible = "fixed-clock";
        reg = <1>;
        #clock-cells = <0>;
        clock-frequency = <24000000>;
        clock-output-names = "osc";
    };
};

1.2.2. 串口 - uart

用于串口信息打印,因为在 chosen 中指定 uart1 为标准输出串口,所以只保留了 uart1。

chosen {
    stdout-path = &uart1;
};

uart1 设备树节点信息

uart1: serial@02020000 {
    compatible = "fsl,imx6ul-uart", "fsl,imx6q-uart", "fsl,imx21-uart";
    reg = <0x02020000 0x4000>;
    interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&clks IMX6UL_CLK_UART1_IPG>,
    		 <&clks IMX6UL_CLK_UART1_SERIAL>;
    clock-names = "ipg", "per";
    status = "disabled";
};

1.2.3. anatop调节器

Anatop调节器驱动器提供低电平控制电源调节器,并选择电压电平。该设备驱动程序利用调节器核心驱动程序访问Anatop硬件控制寄存器,仅在i.MX 6和i.MX 7上支持。
下面是imx6ull设备树中的内容:

anatop: anatop@020c8000 {
    compatible = "fsl,imx6ul-anatop", "fsl,imx6q-anatop",
    "syscon", "simple-bus";
    reg = <0x020c8000 0x1000>;
    interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
                <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
                <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
	
    reg_arm: regulator-vddcore@140 {	    /* cpu 电压调节器 */
        compatible = "fsl,anatop-regulator";
        regulator-name = "cpu";
        regulator-min-microvolt = <725000>;		/* 最小电压(微伏) */
        regulator-max-microvolt = <1450000>;	
        regulator-always-on;
        anatop-reg-offset = <0x140>;			/* Anatop MFD寄存器偏移量 */
        anatop-vol-bit-shift = <0>;				/* 寄存器的位移位 */
        anatop-vol-bit-width = <5>;				/* 寄存器中使用的位数 */
        anatop-delay-reg-offset = <0x170>;		 /* Anatop MF单步时间寄存器偏移量 */
        anatop-delay-bit-shift = <24>;			/* 单步时间寄存器位偏移 */
        anatop-delay-bit-width = <2>;			/* 单步时间寄存器使用位数 */
        anatop-min-bit-val = <1>;				/* 此寄存器最小值 */
        anatop-min-voltage = <725000>;			/* 最小电压 */
        anatop-max-voltage = <1450000>;			/* 最大电压 */
    };

    reg_soc: regulator-vddsoc@140 {		    /* soc 电压调节器 */
        compatible = "fsl,anatop-regulator";
        regulator-name = "vddsoc";
        regulator-min-microvolt = <725000>;
        regulator-max-microvolt = <1450000>;
        regulator-always-on;
        anatop-reg-offset = <0x140>;
        anatop-vol-bit-shift = <18>;
        anatop-vol-bit-width = <5>;
        anatop-delay-reg-offset = <0x170>;
        anatop-delay-bit-shift = <28>;
        anatop-delay-bit-width = <2>;
        anatop-min-bit-val = <1>;
        anatop-min-voltage = <725000>;
        anatop-max-voltage = <1450000>;
    };
};
1.2.3.1 anatop 调节器说明

linux-imx6/Documentation/devicetree/bindings/regulator/anatop-regulator.txt

Anatop Voltage regulators

Required properties:
- compatible: Must be "fsl,anatop-regulator"
- anatop-reg-offset: Anatop MFD register offset
- anatop-vol-bit-shift: Bit shift for the register
- anatop-vol-bit-width: Number of bits used in the register
- anatop-min-bit-val: Minimum value of this register
- anatop-min-voltage: Minimum voltage of this regulator
- anatop-max-voltage: Maximum voltage of this regulator

Optional properties:
- anatop-delay-reg-offset: Anatop MFD step time register offset
- anatop-delay-bit-shift: Bit shift for the step time register
- anatop-delay-bit-width: Number of bits used in the step time register

Any property defined as part of the core regulator
binding, defined in regulator.txt, can also be used.

Example:

	regulator-vddpu {
		compatible = "fsl,anatop-regulator";
		regulator-name = "vddpu";
		regulator-min-microvolt = <725000>;
		regulator-max-microvolt = <1300000>;
		regulator-always-on;
		anatop-reg-offset = <0x140>;
		anatop-vol-bit-shift = <9>;
		anatop-vol-bit-width = <5>;
		anatop-delay-reg-offset = <0x170>;
		anatop-delay-bit-shift = <24>;
		anatop-delay-bit-width = <2>;
		anatop-min-bit-val = <1>;
		anatop-min-voltage = <725000>;
		anatop-max-voltage = <1300000>;
	};

###1.2.4. USDHC—Ultra-Secure Digital Host Controller

超安全数字主机控制器,MMC/SD/eSD/SDXC/eMMC 可以连接到任何USDHC块,并且可以通过将 4KB 的数据从MMC/SDESD/eMMC设备复制到内部RAM来启动。

下面是关于usdhc1节点,.dtsi 中 usdhc1: usdhc@02190000 节点内容如下:

usdhc1: usdhc@02190000 {
    compatible = "fsl,imx6ull-usdhc", "fsl,imx6sx-usdhc";		/* 匹配驱动 */
    reg = <0x02190000 0x4000>;								  /* 寄存器地址 */
    interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;			    /* 中断 */
    clocks = <&clks IMX6UL_CLK_USDHC1>,	 	/* 表示具有三个时钟输入设备;分别为ipg、ahb、per*/
        	<&clks IMX6UL_CLK_USDHC1>,
    		<&clks IMX6UL_CLK_USDHC1>;
    clock-names = "ipg", "ahb", "per";
    /* 提供两路时钟 */
    assigned-clocks = <&clks IMX6UL_CLK_USDHC1_SEL>, <&clks IMX6UL_CLK_USDHC1>;
    assigned-clock-parents =  <&clks IMX6UL_CLK_PLL2_PFD2>;	/* 父时钟 */
    assigned-clock-rates = <0>, <132000000>;		/* 两路时钟频率分别为 0MHz 和 132MHz */
    bus-width = <4>;							  /* 总线位宽 */
    fsl,tuning-step= <2>;						   /* 调优过程中增加的延迟单元 */
    status = "disabled";
};

.dts 中 &usdhc1 节点内容如下:

&usdhc1 {
	pinctrl-names = "default", "state_100mhz", "state_200mhz";
	pinctrl-0 = <&pinctrl_usdhc1>;  			// pinctrl子系统管脚配置
	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
	cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;      //gpio1_19,低电平有效 检测是否在

	keep-power-in-suspend;  //表示待机是不掉电
	enable-sdio-wakeup;  	// 支持1-bit/4-bit SD和SDIO模式,1-bti/4-bit SD/8-bit MMC模式
	vmmc-supply = <&reg_sd1_vmmc>;  //指向regulator设备树节点
	status = "okay";
};

regulator 节点用来供电,内容如下:

reg_sd1_vmmc: regulator@1 {
    compatible = "regulator-fixed";
    regulator-name = "VSD_3V3";
    regulator-min-microvolt = <3300000>;
    regulator-max-microvolt = <3300000>;
    gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
    enable-active-high;
};

1.2.5. 时钟控制模块节点 - CCM

该节点匹配到时钟配置文件(clk_imx6ul.c),关于CCM 时钟控制模块在时钟系统中说明。

clks: ccm@020c4000 {
    compatible = "fsl,imx6ul-ccm";	/* 匹配驱动(clk_imx6ul.c) */
    reg = <0x020c4000 0x4000>;	   /* CCM Memory Map/Register 地址范围0x020c4000-0x020c8000 */
    interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
    			 <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
    #clock-cells = <1>;
    clocks = <&ckil>, <&osc>;
    clock-names = "ckil", "osc";
};

1.3. pinctrl 子系统和 gpio 子系统

###1.3.1. pinctrl 子系统

pinctrl 子系统用于管理芯片的引脚。芯片上拥有众多的片上外设,大多数外设需要通过芯片的引脚与外部器件相连实现相对应的控制,例如 I2C、SPI、LCD、USDHC 等等。而芯片的引脚数量是有限的,为了提高硬件设计的灵活性,一个芯片引脚往往可以作为多个片上外设的功能引脚。
pinctrl 子系统时由芯片厂商实现,用于帮助管理芯片引脚并自动完成引脚的初始化

如下是 imx6ull.dtsi 上的 iomuxc 节点:

iomuxc: iomuxc@020e0000 {
    compatible = "fsl,imx6ul-iomuxc";	/* 匹配驱动 */
    reg = <0x020e0000 0x4000>;			/* 引脚配置寄存器的基地址 */
};

.dtsi 中的 iomuxc 节点主要是当前芯片的通用配置,pinctrl 使用者具体的配置信息在 .dts 文件中描述,如下所示:

&iomuxc {
	pinctrl-names = "default";
    /* 默认状态下,将使用pinctrl_hog_1这个设备点来设置GPIO状态 */
	pinctrl-0 = <&pinctrl_hog_1>;
    
	imx6ul-evk {
		pinctrl_hog_1: hoggrp-1 {
			fsl,pins = <
				/* 复用GPIO1_IO9,通过读取其高低电平判断SD卡有没有插入 */
				MX6UL_PAD_UART1_RTS_B__GPIO1_IO19	0x17059 /* SD1 CD */
                /* SD1 VSELECT 用来选择使用3.3v还是1.8v */
				MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT	0x17059 
				MX6UL_PAD_GPIO1_IO09__GPIO1_IO09        0x17059 /* SD1 RESET */
			>;
		};

		pinctrl_uart1: uart1grp {
			fsl,pins = <
				MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
				MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
			>;
		};
        
		pinctrl_usdhc1: usdhc1grp {
			fsl,pins = <
				MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x17059
				MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x10071
				MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059
				MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059
				MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059
				MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059
			>;
		};

		pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
			fsl,pins = <
				MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x170b9
				MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100b9
				MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9
				MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9
				MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9
				MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9
			>;
		};

		pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
			fsl,pins = <
				MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x170f9
				MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100f9
				MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9
				MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9
				MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9
				MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9
			>;
		};
	};
};

###1.3.2. gpio 子系统

在没有使用GPIO子系统之前,如过想点亮一个LED,首先要得到led相关的配置寄存器,再手动地读、改、写这些配置寄存器实现控制LED地目的。有了GPIO子系统后这部分工作由GPIO子系统完成。只需要调用GPIO子系统提供地API函数即可完成GPIO地控制动作。

gpio1节点描述如下所示:

gpio1: gpio@0209c000 {
    compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";	  /* 匹配驱动 */
    reg = <0x0209c000 0x4000>;							/* GPIO寄存器基地址 */
    interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,		  /* 中断 */
    			<GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
    gpio-controller;		/* 表示gpio1是个GPIO控制器 */
    #gpio-cells = <2>;
    interrupt-controller;	/* 表示gpio1是个中断控制器 */
    #interrupt-cells = <2>;
};

SD卡使用到GPIO1_IO9

reg_sd1_vmmc: regulator@1 {
    compatible = "regulator-fixed";
    regulator-name = "VSD_3V3";
    regulator-min-microvolt = <3300000>;
    regulator-max-microvolt = <3300000>;
    gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;		/* GPIO1_IO9 高电平有效 */
    enable-active-high;
};

##1.4. 中断子系统

// 顶层GIC控制器
intc: interrupt-controller@00a01000 {
    compatible = "arm,cortex-a7-gic";
    
    /* #interrupt-cells = <3>; 说明子中断调用需要3个cell说明该中断
     * 第一个cell代表中断类型,SGI 软件中断、PPI 私有外设中断、SPI 共享外设中断
     * 第二个cell表示中断号
     * 第三个cell表示触发类型*/
    #interrupt-cells = <3>;		
    interrupt-controller;	    /* 中断控制器 */
    reg = <0x00a01000 0x1000>,
    	<0x00a02000 0x100>;
};

从imx6ull中摘录 gpio1 的关联中断,如下:

// gpio中断控制器
gpio1: gpio@0209c000 {
    compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
    reg = <0x0209c000 0x4000>;
    interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
    			<GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
    gpio-controller;		  /* gpio 中断控制器 */
    
    /* #gpio-cells = <2>; 说明子中断调用需要2个cell说明该中断
     * 第一个cell代表中断号
     * 第二个cell的 bit[3:0] 用来表示触发类型,
     * 1:上升沿触发,2:下降沿触发,4:高电平触发,8:低电平触发 */
    #gpio-cells = <2>;		
    interrupt-controller;	
    #interrupt-cells = <2>;
};

gpio1节点中没有标注其父节点,这是需要看gpio1父节点的中断父节点(继承关系),gpio1父节点为soc节点:

soc {
    #address-cells = <1>;
    #size-cells = <1>;
    compatible = "simple-bus";
    interrupt-parent = <&gpc>;
    ranges;
}

所以 gpio1 节点的中断父节点为 gpc 中断控制器。

注:只需要1个 cell 说明中断时,cell 表示中断号。

1.5. 通用定时器 - GPT

cortex-A7 拥有2个EPIT定时器和2个GPT定时器。

imx6ull使用的是 GPT 定时器(具体说明见 “ **IMX6ULL参考手册 **” 的 “ Chapter 30 General Purpose Timer (GPT) ”章节)

  • GPT 定时器简介
    1. GPT定时器时32位向上寄存器。
    2. GPT定时器有两路输入捕获和三路输出比较。
    3. GPT定时器有一个12位分频器。
    4. GPT时钟源可以选择。
    5. GPT定时器有两种工作模式:Restart和Free-Run模式(通过控制寄存器GPT_CR的bit9 FRR设置)。\
      • Restart模式:此模式下,当计数值和比较寄存器中的值相等的时候,计数值清零,重新开始向上计数(只有比较通道1才有此模式,比较通道2,3没有)。
      • Free-Run模式:此模式下,当比较事件发生后并不会复位寄存器,而是继续计数,直到计到0xFFFFFFFF,然后重新回到0x00000000。

设备树中 gpt1: gpt@02098000 节点内容如下所示:

/* GPT(General Purpose Timer)通用定时器 */
gpt1: gpt@02098000 {
    compatible = "fsl,imx6ul-gpt", "fsl,imx31-gpt";
    reg = <0x02098000 0x4000>;
    interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;		/* 中断 */
    clocks = <&clks IMX6UL_CLK_GPT1_BUS>,				/* 输入时钟 */
    		 <&clks IMX6UL_CLK_GPT_3M>;
    clock-names = "ipg", "osc_per";
};

-------------- 设备树中 OCOTP 没查到较官方的说明 -------------------

1.6. OCOTP

OCOTP_CTRL 详细信息见 “IMX6ULL参考手册” 的 “Chapter 37 On-Chip OTP Controller (OCOTP_CTRL) ”章节

OCOTP_CTRL(片上 OTP 控制器;OCOTP 包含 eFUse)

OTP 分为 eFuse OTP NVMAnti-Fuse OTP NVM

eFuse(electric-fuse,电子保险丝)是一次性可编程存储器,在芯片出厂之前会被写入信息,在一个芯片中,eFuse的容量通常很小。

Fuse是i.Mxxx芯片中一块特殊存储区域,用于存放全部芯片配置信息,其中一部分配置信息和Boot相关。

1.6.1 启动关联

内核的启动从片上的boot rom开始执行,SBMR - 启动模式寄存器
boot rom根据 BOOT_MODE[1:0] 的值及 fuse 或 GPIO 对应状态确定启动设备。
SRC_SBMR2 寄存器的 BT_FUSE_SEL 位与 BOOT_MODE[1:0] 共同决定了启动设置是否由GPIO引脚控制。

00 ------- Boot From Fuses(根据 efuse 的值确定启动流程)
01 ------- Serial Downloader(uart/USB)
10 ------- Internal Boot模式(Serial NOR/NAND、SD/EMMC………)
11 ------- 预留

BOOT_MODE[1:0] = 10,BT_FUSE_SEL = 0时,SRC_SBMR寄存器的值将被GPIO覆盖;如果BT_FUSE_SEL = 1
时,SRC_SBMR寄存器的特殊位将由eFUSE设置。

BOOT_MODE[1:0] = 00,BT_FUSE_SEL = 0时,启动配置熔丝没有被编程,自动跳转到serial downloader;BT_FUSE_SEL = 1时,启动配置eFUSE已经编程,执行常规启动流程。

以下是设备树中对 ocotp 节点的描述:

ocotp: ocotp-ctrl@021bc000 {
    compatible = "fsl,imx6ull-ocotp", "syscon";
    reg = <0x021bc000 0x4000>;
    clocks = <&clks IMX6UL_CLK_OCOTP>;
};

2. 时钟系统

2.1. 时钟控制模块 - CCM

i.MX6U 的时钟系统由时钟控制模块(CCM)进行控制,其主要功能如下:

  • 使用PLL锁相环电路将参考时钟倍频,得到频率更高的时钟。
    为芯片内核和外设提供可选的时钟源。i.MX6U 共有 7 个 PLL 锁相环电路,分别为:
    ARM PLL(PLL 1)、System PLL(PLL 2)、USB1 PLL(PLL 3)、Audio PLL(PLL 4)、Video PLL(PLL5)、ENET PLL(PLL 6)、USB2 PLL(PLL 7)。
  • 提供PLL控制寄存器、时钟选择寄存器、时钟分频寄存器。
  • 控制低功耗模块。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s3tPmBzX-1685697696372)(photo/CCM.png)]

  1. **CCM_CLK_IGNITION **

管理从外部晶振时钟到稳定的根时钟输出的整个过程。GPC 是 General Power Controller 的缩写,即总电源管理模块,它不属于CCM。但是系统最高时钟频率受系统电压影响,CCM又可以控制总电源管理模块(GPC)进入待机或低功耗状态。

  1. CCM_ANALOG - PLL时钟产生

CCM_ANALOG 为 CCM 的模拟部分,作用是将频率较低的参考时钟(例如24MHz的XTALOSC时钟)使用PLL锁相环电路倍频到更高的时钟。 CCM_CLK_SWITCHER模块接收来自CCM_ANALOG模块的锁相环时钟输输出,以及锁相环的旁路时钟, 并为CCM_CLK_ROOT_GEN子模块生成切换时钟输出(pll1_sw_clk)。i.MX 6U共有7个PLL锁相环电路,可以独立配置。 其中PLL2与PLL3结合PFD能够输出多个频率可调的时钟。

  1. CCM_CLK_ROOT_GEN - 根时钟生成

CCM_CLK_ROOT_GEN接收来自CCM_CLK_SWITCHER模块的PLL或PFD时钟,经过时钟的选择、分频等操作之后产生并输出根时钟。根时钟将会作内核或外设的时钟源。

  1. CCM_HND_SK - 时钟同步

当更改某些时钟的时钟源时需要进行时钟的同步 CCM_HND_SK 模块用于管理时钟握手,即时钟的同步。

  1. CCM_LPM - 低功耗管理与时钟启用模块

CCM_LPM用于管理低功耗模式,管理时钟的开启与关闭。CCM_CLK_LOGIC,根据来自CCM_LPM模块和CCM_IP的信号产生时钟启用或关闭信号。

  1. LPCG - 低功耗时钟门控模块

低功耗时钟门控模块(LPCG)根据CCM_CLK_LOGIC模块输出信号控制时钟输出。时钟越多、频率越高功耗也就越高。关闭没有使用的时钟或降低时钟频率能够有效的降低功耗。

2.2. 时钟生成

2.2.1. 时钟源(晶振)

  • 高频振荡器(典型频率为24 MHz)
  • 低频实时时钟振荡器(典型频率为32.768 KHz)组成。

2.2.2. PLL

时钟源分为了 7 组 PLL,且 PLL2 和 PLL3 各分了4组 PFD。

  • **PLL1(ARM PLL) **供 ARM 内核使用的, ARM 内核时钟就是由此 PLL生成的,最高可倍频1.3GHz。

  • **PLL2(System_PLL or 528_PLL)**固定的 22 倍频。此外还有 4 路 PFD,分别为 PLL2_PFD0~PLL2_PFD3,这 4 路 PFD 和 528_PLL共同作为其它很多外设的根时钟源。

  • **PLL3(USB1_PLL)**固定的 22 倍频。此外还有 4 路 PFD,分别为:PLL3_PFD0~PLL3_PFD3,这 4 路 PFD 和 480_PLL共同作为其它很多外设的根时钟源。

  • PLL4(Audio PLL)用于音频相关的外设,此路 PLL的倍频可以调整,范围650MHz~1300MHz,最终输出的时候也可以进行分频,可选 1/2/4 分频

  • **PLL5(Video PLL)**用于显示相关的外设,比如LCD,此路 PLL 的倍频可以调整,范围650MHz~1300MHz,最终输出的时候还可以进行分频, 可选 1/2/4/8/16 分频

  • PLL6(ENET_PLL)用于网络所需时钟,固定为 20+5/6 倍频,在此 PLL 的基础上生成 25/50/100/125MHz的网络时钟

  • **PLL7(USB2_PLL)**USB2PHY使用,固定20倍频,480MHz。

2.3. CCM时钟树 - Clock Tree

时钟树主要分4个部分:

  • Clock Switcher

  • Clock Root Generator

  • Low Power Clock Gating module(LPCG)

  • System Clocks

在这里插入图片描述

2.3.1. 时钟选择 - Clock Switcher

Clock Switcher 是多次通过选择器来选择时钟源 (CCM_CCSR 寄存器)来选择最终的时钟。

时钟选择如下图示:

在这里插入图片描述

结合上图和 CCM_CCSR 寄存器
以 pll1_sw_clk 的时钟选择为例,pll1_sw_clk 可选时钟源有 PLL1(996M)、osc_clk(24M)、PFD2(400M)和 PLL2(528M)。CCM_CCSR 寄存器结构如下所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I3AC7TFa-1685697696376)(photo/CCM_CCSR.png)]

2.3.2. 根时钟生成 - Clock Root Generator

如下图所示,根时钟生成使用3个寄存器(CCM_CBCDR、CCM_CBCMR 和 CCM_CSCMR1)进行一系列操作最终得到对应的根时钟(AXI_CLK_ROOT、AHB_CLK_ROOT 、 IPG_CLK_ROOT等···)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SEekB9yf-1685697696378)(photo/Clock root Generator.png)]

2.3.2.1. AHB_CLK_ROOT、PERCLK_CLK_ROOT 配置为 132MHz 和 66MHz
Clock RootDefault Frequency (MHz)Maximum Frequency (MHz)
ARM_CLK_ROOT12528
MMDC_CLK_ROOT
FABRIC_CLK_ROOT
24396
AXI_CLK_ROOT12264
AHB_CLK_ROOT6132
PERCLK_CLK_ROOT366

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5FWTiITR-1685697696379)(photo/132MHz.png)]

  • AHB_CLK_ROOT – 132MHz

    AHB_CLK_ROOT根时钟经过了两个(1、2)选择器和一个分频器(3)最终输出132Mhz,过程如下:

    1. 选择pre_periph_clk的时钟源,可以选择PLL2、PLL2_PFD2、PLL2_PFD0和PLL2_PFD2/2。
      寄存器CCM_CBCMR 的 PRE_PERIPH_CLK_SEL 位选择 PLL2_PFD2(01),PLL2_PFD2=396MHz。

      PRE_PERIPH2_CLK_SEL位:pre_periph2 时钟源选择,00 选择 PLL2,01 选择 PLL2_PFD2,10 选择 PLL2_PFD0,11 选择 PLL4。
      
    2. 选择periph_clk的时钟源,由寄存器CCM_CBCDR的ERIPH_CLK_SEL位与PLL_bypass_en2组成的或门来选择。寄存器 CCM_CBCDR 的 PERIPH_CLK_SEL选择 PLL2,则 periph_clk = pr_periph_clk = 396MHz。

      PERIPH_CLK_SEL位:peripheral 主时钟选择,如果为 0 的话选择 PLL2,如果为 1 的话选择 periph_clk2_clock。修改此位会引起一次与 MMDC 的握手,所以修改完成以后要等待握手完成,握手完成信号由寄存器 CCM_CDHIPR 中指定位表示。
      
    3. CBCDR的AHB_PODF位来设置AHB_CLK_ROOT的分频值,1~8分频8种,AHB_CLK_ROOT = 132MHz的话就应该设置为3分频:396/3 = 132MHz。

      AHB_PODF:ahb 时钟分频,可设置 0~7,分别对应 1~8 分频。修改此位会引起一次与MMDC 的握手,所以修改完成以后要等待握手完成,握手完成信号由寄存器 CCM_CDHIPR 中指定位表示。
      
  • PERCLK_CLK_ROOT – 66MHz

    1. 因为 PERCLK_CLK_ROOT 的时钟源使用的是 peripheral,所以直接通过CBCDR的 IPG_PODF 位来设置PERCLK_CLK_ROOT 的分频值为 2 分频:132/2=66MHz。

      IPG_PODF:ipg 时钟分频,可设置 0~3,分别对应 1~4 分频。
      
2.3.2.2. MMDC 握手
  • 引起MMDC握手信号

    修改以下分频器和选择器时候会引起握手信号,寄存器CCM_CDHIPR中保存着握手信号是否完成,如果相应的位为1的话就表示握手没有完成,如果为0的话就表示握手完成。:

    mmdc_podf、periph_clk_sel、periph2_clk_se、arm_podf、ahb_podf
    
  • 其他不需要握手的更新PODF需要:

    1. 在更新PODF值之前关闭输出时钟;
    2. 更新PODF值稳定后接通;

    在不关闭输出时钟的情况下更新 PODF 会发生意外,例如无时钟输出;

2.3.2.2. CCM_CBCDR、CCM_CBCMR 、CCM_CSCMR1 和CCM_CCDR寄存器
  • CCM_CBCDR 寄存器结构

在这里插入图片描述

寄存器 CCM_CBCDR 每位的含义如下:

PERIPH_CLK2_PODF:periph2 时钟分频,可设置 0~7,分别对应 1~8 分频。
PERIPH2_CLK_SEL:选择 peripheral2 的主时钟,如果为 0 的话选择 PLL2,如果为 1 的话选择periph2_clk2_clk。修改此位会引起一次与 MMDC 的握手,所以修改完成以后要等待握手完成,握手完成信号由寄存器 CCM_CDHIPR 中指定位表示。
PERIPH_CLK_SEL:peripheral 主时钟选择,如果为 0 的话选择 PLL2,如果为 1 的话选择 periph_clk2_clock。修改此位会引起一次与 MMDC 的握手,所以修改完成以后要等待握手完成,握手完成信号由寄存器 CCM_CDHIPR 中指定位表示。
AXI_PODF:axi 时钟分频,可设置 0~7,分别对应 1~8 分频。
AHB_PODF:ahb 时钟分频,可设置 0~7,分别对应 1~8 分频。修改此位会引起一次与MMDC 的握手,所以修改完成以后要等待握手完成,握手完成信号由寄存器 CCM_CDHIPR 中指定位表示。
IPG_PODF:ipg 时钟分频,可设置 0~3,分别对应 1~4 分频。
AXI_ALT_CLK_SEL:axi_alt 时钟选择,为 0 的话选择 PLL2_PFD2,如果为 1 的话选择PLL3_PFD1。
AXI_CLK_SEL:axi 时钟源选择,为 0 的话选择 periph_clk,为 1 的话选择 axi_alt 时钟。
FABRIC_MMDC_PODF:fabric/mmdc 时钟分频设置,可设置 0~7,分别对应 1~8 分频。
PERIPH2_CLK2_PODF:periph2_clk2 的时钟分频,可设置 0~7,分别对应 1~8 分频。

  • CCM_CBCMR 寄存器结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cdwB3kdi-1685697696380)(photo/CCM_CBCMR.png)]

LCDIF1_PODF:lcdif1 的时钟分频,可设置 0~7,分别对应 1~8 分频。
PRE_PERIPH2_CLK_SEL:pre_periph2 时钟源选择,00 选择 PLL2,01 选择 PLL2_PFD2,10 选择 PLL2_PFD0,11 选择 PLL4。
PERIPH2_CLK2_SEL:periph2_clk2 时钟源选择为 0 的时候选择 pll3_sw_clk,为 1 的时候选择 OSC。
PRE_PERIPH_CLK_SEL:pre_periph 时钟源选择,00 选择 PLL2,01 选择 PLL2_PFD2,10 选择 PLL2_PFD0,11 选择 PLL2_PFD2/2。
PERIPH_CLK2_SEL:peripheral_clk2 时钟源选择,00 选择 pll3_sw_clk,01 选择 osc_clk,10 选择 pll2_bypass_clk。

  • CCM_CSCMR1 寄存器结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X899ofLs-1685697696381)(photo/CCM_CSCMR1.png)]

CCM_CSCMR1 寄存器主要用于外设时钟源的选择,重点关注以下两位
PERCLK_CK_SEL:perclk 时钟源选择,为 0 的话选择 ipg clk,为 1 的话选择 osc clk。
PERCLK_PODF:perclk 的时钟分频,可设置 0~7,分别对应 1~8 分频。

  • CCM_CCDR 寄存器结构

在这里插入图片描述

2.4. CCM 内存映射/寄存器

2.4.1. CCM Memory Map/Register

如下表为CCM内存映射地址及寄存器名称,寄存器描述见 ’IMX6ULL参考手册‘ ‘18.6 CCM Memory Map/Register Definition’

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MOGZilTN-1685697696383)(photo/CCM memory map.png)]

2.4.2. CCM_ANALOG memory map

本节介绍模拟锁相环的寄存器。具有相同描述的寄存器被分组在{}中。各种锁相环的寄存器偏移量如下:

  • ARM PLL: {0h000, 0h004, 0h008, 0h00C}.
  • USB1 PLL: {0h010, 0h014, 0h018, 0h01C}, {0h0F0, 0h0F4, 0h0F8, 0h0FC}.
  • System PLL: {0h030, 0h034, 0h038, 0h03C}, 0h040, 0h050, 0h060, {0h100, 0h104,0h108, 0h10C}.
  • Audio / Video PLL: {0h070, 0h074, 0h078, 0h07C}, 0h080, 0h090, {0h0A0, 0h0A4,0h0A8, 0h0AC}, 0h0B0, 0h0C0

在这里插入图片描述

寄存器描述见’IMX6ull参考手册18.7.1 Analog ARM PLL control Register (CCM_ANALOG_PLL_ARMn)

  • 29
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值