历史上的今天
今天是:2024年12月21日(星期六)
2021年12月21日 | tiny4412 时钟测试
2021-12-21 来源:eefocus
前面分析了 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 部分的频率配置到该表推荐值以下,程序就正常运行了。
史海拾趣
|
蒙特卡罗(Monte Carlo)方法,或称计算机随机模拟方法,是一种基于“随机数”的计算方法。 蒙特卡洛模拟是用来解决工程和经济中的非确定性问题,通过成千上万次的模拟,涵盖相应的可能概率分布空间,从而获得一定概率下的不同数据和频度分布,通过 ...… 查看全部问答> |
|
血液透析疗法是针对肾衰竭患者进行的新疗法。目前,血液透析疗法也是国内外应用最广的治疗肾衰竭的方法,但因其治疗对象多为危重患者,而且治疗过程风险高,出现任何一个小故障都有可能引起严重的医疗事故,所以血液透析装置的安全防护要求极高。本 ...… 查看全部问答> |
|
eboot.bin的烧录地址问题(MLC nandflash) 之前一直是在开发板上用nor 启动的方式来烧nand。可生产的话肯定是需要用烧录器烧的。我需要烧入的文件是:block0img.nb0,eboot.bin。在NBL2中可以看到:#define VFL_EBOOT_START_BLOCK (3)。所以我烧到了第三块。可是没有反应。需要 ...… 查看全部问答> |
|
EVC中我通过classwizard添加一个::OnCreate(LPCREATESTRUCT lpCreateStruct),为什么没执行到啊?如何让他能执行 EVC中我通过classwizard添加一个::OnCreate(LPCREATESTRUCT lpCreateStruct),为什么没执行到啊?如何让他能执行到呢?… 查看全部问答> |
|
HidP_GetCaps能在Kernel-Mode Driver中使用吗 想在自己的驱动里通过设备接口读其他设备的usage和usagepage,一系列操作之后获得了Preparese Data,想通过HidP_GetCaps函数获取Capabilities,可是加上这个函数后编译出的sys不能正常加载,设备管理器中显示我的设备无法正常加载驱动。 只要把这个 ...… 查看全部问答> |




