tiny4412 时钟测试
前面分析了 4412 时钟体系,本文来简单测试一下,参考韦东山老师的 Linux 应用完全开发手册4412 (上)
第一实验:
三星公司的BL1会将ARMCLK初始化为400MHz,我们关闭APLL,让 ARMCLK 工作在 24MHz,查看LED闪烁是否缓慢
start.S
- .text
- .globl _start
- _start:
- ldr sp, =0x02027800
- // 调用C函数之前必须设置栈,栈用于保存运行环境,给局部变量分配空间
- // 参考ROM手册P14, 我们把栈指向BL2上方1K处(1K已经够用),
- // 即:0x02020000 (iRAM基地址) + 5K(iROM代码用) + 8K(BL1用) + 16K(BL2用) + 1K(用作栈))
- bl main // 调用main函数(main这个名称不是固定的,可以随意改)
- halt_loop:
- b halt_loop
- #define GPM4CON (*(volatile unsigned int *)0x110002E0)
- #define GPM4DAT (*(volatile unsigned int *)0x110002E4)
- void delay(volatile int time)
- {
- for(; time > 0; time-- )
- ;
- }
- int main(void)
- {
- unsigned long tmp = 0;
- int i = 0;
- /*
- * GPM4_0-GPM4_3 设置为输出功能
- */
- tmp = GPM4CON;
- tmp &= ~0xffff;
- tmp |= 0x1111;
- GPM4CON = tmp;
- /*
- * 实现流水灯
- */
- system_clock_init();
- while(1)
- {
- GPM4DAT = i;
- if (++i == 16)
- i = 0;
- delay(9999999);
- }
- return 0;
- }
- // 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;
- }
- objs := start.o led.o clock_init.o
- led.bin : $(objs)
- arm-linux-ld -Tled.lds -N -o led.elf $^
- arm-linux-objcopy -O binary -S led.elf [email protected]
- arm-linux-objdump -D -m arm led.elf > led.dis
- %.o:%.c
- arm-linux-gcc -Wall -marm -c -O2 -o [email protected] $<
- %.o:%.S
- arm-linux-gcc -Wall -marm -c -O2 -o [email protected] $
- clean:
- rm -f *.dis *.bin *.elf *.o
- SECTIONS {
- . = 0x02023400;
- .text : { *(.text) }
- .rodata ALIGN(4) : {*(.rodata*)}
- .data ALIGN(4) : { *(.data*) }
- .bss ALIGN(4) : { *(.bss) *(COMMON) }
- }
第二个实验:
将 ARMCLK 提升到1400MHz ,观察LED闪烁是否变快。只更改 clock_init.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)
- {
- /* 1. 在设置APLL之前, 先设置时钟源为晶振 */
- CLK_SRC_CPU = 0x0;
- /* 2. 设置APLL */
- /* 2.1 设置锁定时间: APLL_CON0中PDIV=3, 所以APLL_LOCK = 270x3 */
- APLL_LOCK = 270 * 3;
- /* 2.2 设置分频参数 */
- CLK_DIV_CPU0 = 0x00160760;
- CLK_DIV_CPU1 = 0x00000106;
- /* 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;
- }
三星给出了 high-performance 状态下的频率值,我将 cpu 部分的频率配置到该表推荐值以下,程序就正常运行了。