tiny4412 时钟测试

本文通过两个实验测试4412平台的时钟系统。首先,降低ARMCLK至24MHz验证LED闪烁速度变化;其次,提高ARMCLK至1400MHz,并调整相关寄存器值,确保系统稳定运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  前面分析了 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
led.c
#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;
}
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)
{
 /* IROM或BL1设置了APLL,
  * 本程序设置不启动APLL,
  * 而是使在晶振时钟, 以体验一下LED闪灯变慢
  */
   CLK_SRC_CPU = 0x0;
}
Makfile
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 $@
	arm-linux-objdump -D -m arm led.elf > led.dis
%.o:%.c
	arm-linux-gcc -Wall -marm -c -O2 -o $@ $<
%.o:%.S
	arm-linux-gcc -Wall -marm -c -O2 -o $@ $
clean:
	rm -f *.dis *.bin *.elf *.o
led.lds
SECTIONS {  
. = 0x02023400;  
.text : { *(.text) }  
.rodata ALIGN(4) : {*(.rodata*)}  
.data ALIGN(4) : { *(.data*) }  
.bss ALIGN(4) : { *(.bss) *(COMMON) }  
}  
  实验现象应该是相比 led.c 中不加 system_clock_init() 的时候,LED闪烁的非常缓慢。

第二个实验:

  将 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;
}


  一开始,测试时,我试图只把ARMCLK提升到1400MHz,其余寄存器都使用默认值,但是发现LED闪烁几下程序就会跑飞,根据下图采用默认值的情况下大部分DIV分频系数都是1,因此比如ACLK_COREM0等也都会是 1400MHz,但是它们是无法承受如此高的工作频率。



  三星给出了 high-performance 状态下的频率值,我将 cpu 部分的频率配置到该表推荐值以下,程序就正常运行了。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值