系统时钟概述

zynq7000的时钟系统很简单,首先是PS_CLK输入时钟,这是外部33.33333Mhz晶振时钟,直接输入到三路PLL(锁相环),分别是 ARM PLL、I/O PLL、DDR PLL;ARM PLL给 CPU核心、SCU(用来管理多核通信)、OCM、AXI总线提供时钟;I/O PLL给各类外设包括SDIO、USB、Ethernet等提供时钟;DDR PLL仅用来给DDR2/3提供时钟;而在每一路PLL时钟之后,通向每一个设备之前,会有一个6 bit的programmable Divider用来对PLL时钟分频,分频之后的频率就是每个设备的输入频率。

在PS_CLK与xxx PLL之间有xxx_PLL_CTRL寄存器用来控制PLL的倍频系数,以及控制旁路设置(设置PS_CLK是否直接绕过PLL给各类设备提供时钟)。

系统框图如下:

SDIO时钟系统超频

SDIO时钟源选择I/O PLL,通过寄存器 SDIO_CLK_CTRL[5:4]位控制,00是选择IO PLL;10选择ARM PLL; 11选择DDR PLL。当然也可以选择ARM/DDR PLL,只是xilinx官方不推荐。

上面提到的6 bit programmable Divider也在这个寄存器中,具体是SDIO_CLK_CTRL[13:8]位控制,可提供1~64分频值,超频要调整的就是这6个bit

接下来就是SDIO的controller,zynq7000的controller是IP解决方案提供商arasan提供的,在zynq-7000.dtsi中的兼容性定义为compatible = "arasan,sdhci-8.9a"; 因此寄存器层驱动也是arasan提供的统一驱动,具体文件在内核根目录下的 drivers/mmc/host/sdhci-of-arasan.c
在controller的寄存器组中也有一个寄存器用于SDIO内部分频,由于这个分频器太过粗糙,只能提供2/4/8/16/32/64/128分频值,因此基本不用。

根据ug585-Zynq-7000-TRM手册,可以知道SDIO_CLK_CTRL寄存器的地址为0XF8000150;
寄存器位定义如下:
 

Field Name

bits

Description

reserved

31:14

保留

DIVISOR

13:8

提供用来分频的分频值来得到需要的频率

reserved

7:6

保留

SRCSEL

5:4

选择PLL时钟源

0x:Select clock IO PLL

10:Select clock ARM PLL

11:Select clock DDR PLL

reserved

3:2

保留

CLKACT1

1

SDIO Controller 1 Clock enable

CLKACT0

0

SDIO Controller 0 Clock enable

对于reserved的位,直接给0即可

数据手册中表示SDIO controller输入频率不得高于63MHZ,但既然超频,那么我们就设定为100Mhz

PS_CLK=33.33333Mhz,读取IO_PLL_CTRL寄存器值可以知道,当前系统倍频值(FDIV)是36,那么IO_PLL时钟频率则是PS_CLK*FDIV=1199.9988MHZ=1200MHZ

我们想得到100Mhz频率,那么12分频即可,则DIVISOR[13:8]=0xC

时钟源选择IO PLL,SRCSEL[5:4]=0x0或者0x1

由于我使用的controller是SDIO0那么 CLKACT1=0x0 CLKACT0=0x1

那么寄存器SDIO_CLK_CTRL的值为:0x0000 0C01

SDIO_CLK_CTRL的地址为0XF8000150

在命令行键入:devmem 0xF8000150 32 0x0C01

此时频率已经为100Mhz

使用dd命令测试发现,现在的SD卡速度已经高达43MB/s,而超频前在50Mhz频率下运行时SD卡频率只有22M/s

经过多种分频测试后发现,在DIVISOR[13:8]=0x7,也就是频率=1200/7=171MHZ的时候,已经是zynq7z010芯片的极限稳定速度,此时速度达到69.7MB/s,已经是官网限定频率和速度的三倍还多,当然,想要达到这样高的信号稳定性,PCB的设计上也一定是非常完美的,此时就要着重吹捧一下我们的硬件工程师宇哥了,要知道我在上一家公司的时候,硬件工程师设计的频率仅1Mhz的can通信外部电路都经常出问题,波形也是差的无法直视。
当DIVISOR[13:8]=0x6,也就是频率=1200/6=200Mhz的时候,通信才出现问题,报I/O error。