博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Tiny4412裸机程序,时钟操作
阅读量:6455 次
发布时间:2019-06-23

本文共 7881 字,大约阅读时间需要 26 分钟。

hot3.png

本文转自:

有了上一节《》的基础,这一节我们来做几个和时钟有关的实验。

其实,Exynos 4412的IROM代码已经设置了PLL,我们可以通过串口把IROM设置的PLL寄存器值打印出来,这些值打印出来是这样的(摘自韦东山老师的《嵌入式Linux系统开发完全手册_基于4412__上册》):

CLK_SRC_CPU = 0x01000001CLK_DIV_DMC0 = 0x00111713CLK_DIV_DMC1 = 0x01011171CLK_SRC_TOP0 = 0x01110000CLK_SRC_TOP1 = 0x00001000CLK_DIV_TOP = 0x00015470CLK_SRC_LEFTBUS = 0x00000001CLK_DIV_LEFTBUS = 0x00000013CLK_SRC_RIGHTBUS = 0x00000001CLK_DIV_RIGHTBUS = 0x00000013APLL_LOCK = 0x00000960MPLL_LOCK = 0x00000000EPLL_LOCK = 0x00000FFFVPLL_LOCK = 0x00000FFFCLK_DIV_CPU0 = 0x00773730CLK_DIV_CPU1 = 0x00000077APLL_CON1 = 0x00003800APLL_CON0 = 0xA0640301MPLL_CON1 = 0x00003800MPLL_CON0 = 0xA0640301EPLL_CON2 = 0x00000080EPLL_CON1 = 0x66010000EPLL_CON0 = 0x00600302VPLL_CON2 = 0x00000080VPLL_CON1 = 0x66016000VPLL_CON0 = 0x006F0302CLK_SRC_CPU = 0x01000001CLK_SRC_DMC = 0x00111000CLK_SRC_TOP0 = 0x01110000CLK_SRC_TOP1 = 0x00001000

现在来计算 ARMCLK的时钟频率:

由上一节《》的介绍我们知道,ARMCLK 有如下计算公式:

如下图所示:

143304_r2UT_2888084.png

由上边打印的寄存器CLK_SRC_CPU 的值为:

十六进制:0x01000001

二进制:0000 0001 0000 0000 0000 0000 0000 0001

  1. BIT[0] 控制第1个MUX (即 MUXAPLL) ,该位值为1.
  2. BIT[16]控制 第2个 MUX( 即MUXCORE) ,该位值为0.

所以由此看出ARMCLK时钟走的是如下的路线:

143414_wID2_2888084.png

所以:ARMCLK = MUXCORE的输出 / DIVCORE / DIVCORE2

ARMCLK = MDIV x FIN / (PDIV x 2 ^ SDIV) / (CORE_RATIO + 1) / (CORE2_RATIO + 1)

= 0x64 x 24MHz / (3 x 2 ^ 1) / (0 + 1) / (0 + 1)

= 400 MHz

本次实验涉及3个小实验:

  1. system_clock_disable_apll:不使用 APLL,让CPU运行于 24MHz 频率,观察 LED 闪烁是否变慢
  2. system_clock_apll:重新设置APLL,让 CPU 运行于1.4GHz频率,观察 LED 闪烁是否变快
  3. system_clock_plls:参考厂家提供的u-boot代码,设置所有PLL供后续章节使用

第一个小实验

实现的目标:不使用 APLL,让CPU运行于 24MHz 频率,观察 LED 闪烁是否变慢

一、程序说明

我们在前一个实验,《》的基础上修改。

start.S大部分相同,只是增加一条函数调用语句

bl system_clock_init // 调用时钟初始化函数

如下图所示:

143609_qhN7_2888084.png

链接脚本system_clock.lds的内容和上一个实验key.lds完全相同,只把名字改了改;Makefile的内容也大部分一样,也只是改了改里边文件的名字,led.c文件和LED实验时完全相同,新增加了文件system_clock.c,代码如下:

/* CMU_CPU */#define CLK_SRC_CPU (*(volatile unsigned int *)0x10044200)#define CLK_DIV_CPU0 (*(volatile unsigned int *)0x10044500)#define CLK_DIV_CPU1 (*(volatile unsigned int *)0x10044504)/* CMU_DMC */#define CLK_SRC_DMC (*(volatile unsigned int *)0x10040200)#define CLK_DIV_DMC0 (*(volatile unsigned int *)0x10040500)#define CLK_DIV_DMC1 (*(volatile unsigned int *)0x10040504)/* CMU_TOP */#define CLK_SRC_TOP0 (*(volatile unsigned int *)0x1003C210)#define CLK_SRC_TOP1 (*(volatile unsigned int *)0x1003C214)#define CLK_DIV_TOP (*(volatile unsigned int *)0x1003C510)/* CMU_LEFTBUS */#define CLK_SRC_LEFTBUS (*(volatile unsigned int *)0x10034200)#define CLK_DIV_LEFTBUS (*(volatile unsigned int *)0x10034500)/* CMU_RIGHTBUS */#define CLK_SRC_RIGHTBUS (*(volatile unsigned int *)0x10038200)#define CLK_DIV_RIGHTBUS (*(volatile unsigned int *)0x10038500)/* locktime */#define APLL_LOCK (*(volatile unsigned int *)0x10044000)#define MPLL_LOCK (*(volatile unsigned int *)0x10044008)#define EPLL_LOCK (*(volatile unsigned int *)0x1003C010)#define VPLL_LOCK (*(volatile unsigned int *)0x1003C020)/* APLL */#define APLL_CON1 (*(volatile unsigned int *)0x10044104)#define APLL_CON0 (*(volatile unsigned int *)0x10044100)/* MPLL */#define MPLL_CON0 (*(volatile unsigned int *)0x10040108)#define MPLL_CON1 (*(volatile unsigned int *)0x1004010c)/* EPLL */#define EPLL_CON2 (*(volatile unsigned int *)0x1003C118)#define EPLL_CON1 (*(volatile unsigned int *)0x1003C114)#define EPLL_CON0 (*(volatile unsigned int *)0x1003C110)/* VPLL */#define VPLL_CON0 (*(volatile unsigned int *)0x1003C120)#define VPLL_CON1 (*(volatile unsigned int *)0x1003C124)#define VPLL_CON2 (*(volatile unsigned int *)0x1003C128)/* * 函数名: * system_clock_init * 功能: 初始化4412的系统时钟 */void system_clock_init(void){	 /* IROM或BL1设置了APLL,	 * 本程序设置不启动APLL,	 * 而是使在晶振时钟, 以体验一下LED闪灯变慢	 */	 CLK_SRC_CPU = 0x0;}

没什么可说的,很简单,前部分是后期会用到的一些寄存器地址的定义,主要的是下边system_clock_init这个函数,在这个函数中将CLK_SRC_CPU寄存器的值设为0,这样ARMCLK的频率将走下面这条路径,设置为24MHZ:

143739_IAPZ_2888084.png

二、编译、烧写实验

按照前几节介绍的方法,将程序上传到服务器编译,并烧写到SD卡上,给开发板上电,可以明显感觉到LED闪烁的频率大大降低,说明我们设置的时钟起作用了,这里就不上图了(上了图大家也看不出来)。

第二个小实验

实现的目标:重新设置APLL,让 CPU 运行于1.4GHz频率,观察 LED 闪烁是否变快

一、程序说明

文件同第一个小实验,只是在它的基础上对system_clock.c文件中的system_clock_init函数进行修改:

/** 函数名: system_clock_init* 功 能: 初始化4412的系统时钟* 最终结果: APLL=1.4GHz*/void system_clock_init(void){	/*	* 1. 在设置APLL之前, 先设置时钟源为晶振	*/	CLK_SRC_CPU = 0x0;	 	/*	* 2. 设置APLL	*/	 	/* 2.1 设置锁定时间: APLL_CON0中PDIV=3, 所以APLL_LOCK = 270x3 */	APLL_LOCK = 270 * 3;	 	/* 2.2 设置分频参数 */	/*	* CORE2_RATIO = 0;	* APLL_RATIO = 2;	* PCLK_DBG_RATIO = 1;	* ATB_RATIO = 6;	* PERIPH_RATIO = 7;	* COREM1_RATIO = 7;	* COREM0_RATIO = 3;	* CORE_RATIO = 0;	*/	CLK_DIV_CPU0 = ((0<<28) | (2<<24) | (1<<20) | (6<<16) | (7<<12) | (7<<8) | (3<<4) | 0);	 	/*	* CORES_RATIO = 5;	* HPM_RATIO = 0;	* COPY_RATIO = 6;	*/	CLK_DIV_CPU1 = ((5 << 8) |(0 << 4) | (6));	 	/* 2.3 设置控制参数并使能PLL */	/* 默认值 */	APLL_CON1 = 0x00803800;	 	/*	* 设置APLL的M,P,S值, APLL输出 = 0xAF x 24MHz / (3 x 2 ^ 0) = 1.4GHz	* 使能APLL	*/	APLL_CON0 = (1<<31 | 0xAF<<16 | 3<<8 | 0x0);	 	/* 3. 设置MUX, 使用APLL的输出 */	CLK_SRC_CPU = 0x01000001;}

注释的已经很清楚了,需要注意的就是:上电之后 IROM设置了APLL ,CPU工作于APLL提供的时钟;当我们要改变 APLL时,要先使得CPU工作于另一个时钟源,即晶振。设置完APLL后,再让CPU重新工作于APLL提供的时钟。

二、编译、烧写实验

按照前几节介绍的方法,将程序上传到服务器编译,并烧写到SD卡上,给开发板上电,可以明显感觉到LED闪烁的频率大大提高(比《》时闪烁的还要快,因为当时CPU运行在400MHZ,现在运行在1.4GHZ),说明我们设置的时钟起作用了,这里就不上图了(上了图大家也看不出来)。

第三个小实验

实现的目标:参考厂家提供的u-boot代码,设置所有PLL供后续章节使用

一、程序说明

文件同第一个小实验,只是在它的基础上对system_clock.c文件中的system_clock_init函数进行修改:

/*	函数名:	system_clock_init	功能:	初始化4412的系统时钟	最终结果:	A=1400000000, M=800000000, E=96000000 V=350000000	ARMCLK=1500000000, DMC=400000000, ACLK200=160000000	ACLK100=100000000, ACLK160=160000000, ACLK133=133333333*/void system_clock_init(void){	/* 1.设置CMU_CPU相关 */	CLK_SRC_CPU = 0x0; // 设置CMU_CPU部分中所有的MUX的源	 	/* 2.设置CMU_DMC相关 */	/*	CORE_TIMERS_RATIO = 0x0;	COPY2_RATIO = 0x0;	DMCP_RATIO = 0x1;	DMCD_RATIO = 0x1;	DMC_RATIO = 0x1;	DPHY_RATIO = 0x1;	ACP_PCLK_RATIO = 0x1;	ACP_RATIO = 0x3;	*/	CLK_DIV_DMC0 = ((0x0 << 28) | (0x0 << 24) | (0x1 << 20) | (0x1 << 16) | (0x1 << 12) | (0x1 << 8) | (0x1 << 4) | (0x3));	CLK_DIV_DMC1 = 0x07071713;	 	/* 3.设置CMU_TOP相关 */	/*	MUX_ONENAND_SEL = 0x0;	MUX_ACLK_133_SEL = 0x0;	MUX_ACLK_160_SEL = 0x0;	MUX_ACLK_100_SEL = 0x0;	MUX_ACLK_200_SEL = 0x0;	MUX_VPLL_SEL = 0x1;	MUX_EPLL_SEL = 0x1;	*/	CLK_SRC_TOP0 = ((0x0 << 28) | (0x0 << 24) | (0x0 << 20) | (0x0 << 16) | (0x0 << 12) | (0x1 << 8) | (0x1 << 4));	CLK_SRC_TOP1 = 0x01111000;	 	/*	ACLK_400_MCUISP_RATIO = 0x1;	ACLK_266_GPS_RATIO = 0x2;	ONENAND_RATIO = 0x1;	ACLK_133_RATIO = 0x5;	ACLK_160_RATIO = 0x4;	ACLK_100_RATIO = 0x7;	ACLK_200_RATIO = 0x4;	*/	CLK_DIV_TOP = ((0x1 << 24) | (0x2 << 20) | (0x1 << 16) | (0x5 << 12) | (0x4 << 8) | (0x7 << 4) | (0x4));	 	/* 3.设置CMU_LEFTBUS相关 */	CLK_SRC_LEFTBUS = 0x10;	 	/*	GPL_RATIO = 0x1;	GDL_RATIO = 0x3;	*/	CLK_DIV_LEFTBUS = ((0x1 << 4) | (0x3));	 	/* 4.设置CMU_RIGHTBUS相关 */	CLK_SRC_RIGHTBUS = 0x10;	 	/*	GPR_RATIO = 0x1;	GDR_RATIO = 0x3;	*/	CLK_DIV_RIGHTBUS = ((0x1 << 4) | (0x3));	 	/* 5.设置各个锁相环(PLL)的locktime */	APLL_LOCK = (0x3 * 270);	MPLL_LOCK = (0x3 * 270);	EPLL_LOCK = (0x2 * 3000);	VPLL_LOCK = (0x2 * 3000);	/*	APLL_RATIO = 0x2;	CORE_RATIO = 0x0;	CORE2_RATIO = 0x0;	COREM0_RATIO = 0x3;	COREM1_RATIO = 0x7;	PERIPH_RATIO = 0x7;	ATB_RATIO = 0x6;	PCLK_DBG_RATIO = 0x1;	*/	CLK_DIV_CPU0 = ((0x0 << 28) | (0x2 << 24) | (0x1 << 20) | (0x6 << 16) | (0x7 <<12) | (0x7 << 8) | (0x3 << 4) | (0x0));	/*	CORES_RATIO = 0x5;	HPM_RATIO = 0x0;	COPY_RATIO = 0x6;	*/	CLK_DIV_CPU1 = ((0x5 << 8) |(0x0 << 4) | (0x6));	 	/* 6.设置APLL = 1400000000 */	APLL_CON1 = 0x00803800;	APLL_CON0 = (1<<31 | 0xAF<<16 | 0x3<<8 | 0x0);	 	/* 7.设置MPLL = 800000000 */	MPLL_CON1 = 0x00803800;	MPLL_CON0 = (1<<31 | 0x64<<16 | 0x3<<8 | 0x0);	 	/* 8.设置EPLL = 96000000 */	EPLL_CON2 = 0x00000080;	EPLL_CON1 = 0x66010000;	EPLL_CON0 = (1<<31 | 0x40<<16 | 0x2<<8 | 0x3);	 	/* 9.设置VPLL = 350000000 */	VPLL_CON2 = 0x00000080;	VPLL_CON1 = 0x66010000;	VPLL_CON0 = (1<<31 | 0x48<<16 | 0x2<<8 | 0x3);	 	/*10.修改源*/	CLK_SRC_CPU = 0x01000001;	CLK_SRC_DMC = 0x00011000;	CLK_SRC_TOP0 = 0x00000110;	CLK_SRC_TOP1 = 0x01111000;}

二、编译、烧写实验

按照前几节介绍的方法,将程序上传到服务器编译,并烧写到SD卡上,给开发板上电,现象和第二个小实验完全相同。

转载于:https://my.oschina.net/cht2000/blog/1622300

你可能感兴趣的文章
获取androdmanifest里面的meta-data
查看>>
mysql拷贝表的几种方式
查看>>
用设计模式去掉没必要的状态变量 —— 状态模式
查看>>
linux安装elasticsearch及遇到的各种问题
查看>>
健忘的正则
查看>>
[转]CMake快速入门教程:实战
查看>>
IntelliJ IDEA创建JavaWeb工程及配置Tomcat部署
查看>>
Markdown用法
查看>>
求最大值及其下标
查看>>
Request header is too large
查看>>
轮播插件swiper.js?
查看>>
网路流24题总结
查看>>
15 个 Android 通用流行框架大全
查看>>
ant 执行java文件,java文件中含中文,显示乱码
查看>>
IE8兼容@media和mp4视频的解决方案
查看>>
第二周总结
查看>>
概率图模型建模、学习、推理资料总结
查看>>
【转】知道这20个正则表达式,能让你少写1,000行代码
查看>>
自定义 启动和关闭 oracle 的命令
查看>>
SQLite数据库、ListView控件的使用
查看>>