1. 程式人生 > >tiny4412開發板時鐘操作示例

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檔案這裡不介紹。