历史上的今天
返回首页

历史上的今天

今天是: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 部分的频率配置到该表推荐值以下,程序就正常运行了。

推荐阅读

史海拾趣

Compact公司的发展小趣事

随着电子市场的日益成熟,Compact公司意识到单纯的技术创新已不足以支撑其长期发展。于是,公司开始积极寻求市场拓展和战略合作的机会。通过与国内外知名企业建立合作伙伴关系,Compact公司成功将其产品打入国际市场,进一步扩大了市场份额。同时,通过与上下游企业的紧密合作,Compact公司实现了产业链的整合,提高了整体运营效率。

Amphenol(安费诺)公司的发展小趣事

在快速发展的过程中,Compact公司始终注重品牌建设和文化传承。公司通过不断提升产品质量和服务水平,树立了良好的品牌形象。同时,公司还注重培养员工的归属感和忠诚度,形成了独特的企业文化。这种文化传承不仅为公司的发展提供了强大的精神动力,还使公司在激烈的市场竞争中保持了独特的竞争力。

国炬(GOOGLL)公司的发展小趣事
OCL电路能够驱动低阻抗的负载,提高了系统的整体效率。
ETRI公司的发展小趣事

自1976年成立以来,ETRI一直致力于打造高效便捷的智慧产业生态圈。在汽车制造、轨道交通等行业中,电气和机械设备是必不可少的。ETRI凭借其卓越的技术实力,为这些行业提供了在各种恶劣环境下都能保持稳定性的产品。无论是在电机马达、编码器、传感器,还是在泵、阀、流量计以及温度计压力表等广泛使用的设备中,ETRI都展现了其行业领先的解决方案。

AMS公司的发展小趣事

随着人工智能的兴起,ETRI也将目光转向了这一领域。他们与首尔市政府合作,在首尔市The Seocho District区内安装了3000台AI摄像头,这些摄像头通过深度学习技术,能够预测犯罪发生的概率,并在必要时提醒警署采取行动。此外,他们还计划分析大量的法庭判决文件和犯罪录像,以优化AI软件的预测能力。

B+B SmartWorx公司的发展小趣事

B+B SmartWorx始终坚持以客户为中心,通过提供优质的产品和服务来满足客户需求。公司相信,客户满意度和产品创新是驱动其增长的关键因素。因此,B+B SmartWorx在设计和制造网络连接设备时,始终注重设备的易用性、可管理性和可靠性。这种对客户的深度理解和持续创新,使得B+B SmartWorx在电子行业中赢得了良好的声誉,并实现了持续稳健的发展。

这些故事基于B+B SmartWorx的发展历程和现有信息,虚构了一些具体情节,旨在展现该公司在电子行业中的成长与变迁。请注意,这些故事可能并不完全准确反映B+B SmartWorx的实际发展情况,如需了解更多关于该公司的具体信息,建议查阅相关官方资料或新闻报道。

问答坊 | AI 解惑

PROTEL99SE电子设计软件使用手册

PROTEL9SE电子设计软件使用手册(英文版)…

查看全部问答>

ns中文手册精美版

ns手册中文精美版…

查看全部问答>

蒙特卡罗分析实现方法

蒙特卡罗(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不能正常加载,设备管理器中显示我的设备无法正常加载驱动。 只要把这个 ...…

查看全部问答>

Linux eink驱动

正准备着手进行Linux eink驱动,欢迎做过了的和正在做的一起探讨!!谢谢!qq\"95221338…

查看全部问答>

请教一个dc-dc变换器问题

请教一个dc-dc变换器问题要求:输入:DC  9-24v         输出:DC  2.5V 1.5A         输出纹波Vp-p≤80mv  &nbs ...…

查看全部问答>