tiny4412开发板时钟操作示例

在上一节总我们介绍了《Exynos4412芯片的时钟管理单元》,有了上一节的基础知识我们就可以写程序操作CPU的时钟了。通过操作led来感受时钟速率的变化。本文总共有三个示例,第一个是写一个LED循环点亮的程序;第二个是将iROM中设置的时钟禁止掉,观察LED变化速率;第三个就是设置CPU的时钟速率为1.4GHz,观察LED的变化速率。

第一个程序很简单,有两个文件start.S和main.c。其中,start.Sz文件中设置栈,然后跳转到C函数中执行。在main.c中设置LED的亮灭。首先,来看start.S内容:

.text
.global _start
_start:
	ldr sp, =0x02027400		//设置栈
	
	bl main					//跳转到mian函数开始执行
	
halt_loop:					//死循环
	b halt_loop

程序很简单,设置栈,关于为什么设置栈这里不再讲述,自己可以去某度搜索。然后就是跳转到main函数中执行,最后就是死循环。

main.c文件的内容如下:

//关于GPM4引脚的宏
#define GPM4CON 		(*(volatile long *)0x110002E0)
#define GPM4DAT 		(*(volatile long *)0x110002E4)

void delay(int n)
{
	while(n--);
}

int main()
{
	int i;
	
	//让LED1、LED2、LED3和LED4循环闪烁
	//1.首先,配置GPM4_0、GPM4_1、GPM4_2和GPM4_3四个引脚为输出
	GPM4CON &= ~(0xFFFF);
	GPM4CON |=  (0x1111);

	//2.循环点亮
	while(1)
	{
		for (i = 2; i <= 5; i++)
		{
			/* 点亮LED : GPIO输出低电平 */
			GPM4DAT &= ~(1 << (i - 2));
			delay(100000);
			/* 熄灭LED : GPIO输出高电平 */
			GPM4DAT |= (1 << (i - 2));
			delay(100000);
		}
	}
	
	return 0;
}

很简单,就是让LED循环点亮;如果不是太懂,可以参照前面的关于操作LED方面的文章。这里不做详细介绍。我们可以观察LED是循环点亮的。一直在哪里死循环。

通过阅读芯片的Spec可以知道在iROM中已经设置了CPU的时钟频率为400MHz,就是关于设置CLK_SRC_CPU、APLL_LOCK、APLL_CON0和CLK_DIV_CPU0等寄存器,关于时钟相关的寄存器的设置大家可以阅读上篇文章。这里不赘述了。

现在,来看第二个程序的文件,是同样的文件名。其中,start.S文件没有更改,只修改了main.c,禁止CPU的时钟使用FOUTAPLL。将CPU的时钟源设置为FINPLL,只需要设置CLK_SRC_CPU寄存器的bit0即可实现。并观察LED亮灭的变化。

main.c的文件内容如下:

//操作时钟的宏
#define CLK_SRC_CPU 	(*(volatile long *)0x10044200)

//关于GPM4引脚的宏
#define GPM4CON 		(*(volatile long *)0x110002E0)
#define GPM4DAT 		(*(volatile long *)0x110002E4)

void delay(int n)
{
	while(n--);
}

int main()
{
	int i;

	//让LED1、LED2、LED3和LED4循环闪烁
	//1.首先,配置GPM4_0、GPM4_1、GPM4_2和GPM4_3四个引脚为输出
	GPM4CON &= ~(0xFFFF);
	GPM4CON |=  (0x1111);

	//将CPU的时钟源设置为FINPLL;将bit0设置为0
	CLK_SRC_CPU &= ~(0x01 << 0);

	//2.循环点亮
	while(1)
	{
		for (i = 2; i <= 5; i++)
		{
			/* 点亮LED : GPIO输出低电平 */
			GPM4DAT &= ~(1 << (i - 2));
			delay(100000);
			/* 熄灭LED : GPIO输出高电平 */
			GPM4DAT |= (1 << (i - 2));
			delay(100000);
		}
	}

	return 0;
}

已经做了详细的注释,将编译处的clock.bin文件烧写到SD中,将开发板设置为SD启动模式,插入SD卡运行发现LED亮灭闪烁的时间和上个试验相比很小,变化很慢。

第三个示例,将CPU的工作频率设置为1.4GHz,观察LED的亮灭情况。main.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)

//关于GPM4引脚的宏
#define GPM4CON 		(*(volatile long *)0x110002E0)
#define GPM4DAT 		(*(volatile long *)0x110002E4)
 
/*
* 函数名: 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;
	//return 0;
}

void delay(int n)
{
	while(n--);
}

int main()
{
	int i;
	
	system_clock_init();

	//让LED1、LED2、LED3和LED4循环闪烁
	//1.首先,配置GPM4_0、GPM4_1、GPM4_2和GPM4_3四个引脚为输出
	GPM4CON &= ~(0xFFFF);
	GPM4CON |=  (0x1111);

	//2.循环点亮
	while(1)
	{
		for (i = 2; i <= 5; i++)
		{
			/* 点亮LED : GPIO输出低电平 */
			GPM4DAT &= ~(1 << (i - 2));
			delay(100000);
			/* 熄灭LED : GPIO输出高电平 */
			GPM4DAT |= (1 << (i - 2));
			delay(100000);
		}
	}

	return 0;
}

将文件上传到服务器,编译并烧写,试验观察LED的亮灭情况。关于程序使用的链接脚本和Makefile文件这里不介绍。

你可能感兴趣的:(tiny4412开发板学习记录)