s3c2440裸机编程-时钟编程(二、配置时钟寄存器)

s3c2440裸机编程-时钟编程(二、配置时钟寄存器)

1.2440时钟时序

下图是2440时钟配置时序:

1.上电后,nRESET复位信号拉低,此时cpu还无法取指令工作。

2.nRESET复位信号结束后变为高电平,此时cpu开始工作。此时cpu主频FCLK=osc。

3.此时可以配置PLL,经过lock time后,FCLK倍频成新的时钟。

2.如何配置时钟

在参考手册的特性里介绍了S3C2440的工作频率,Fclk最高400MHz,Hclk最高136MHz,Pclk最高68MHz。那么 我们干脆配置FCLK:HCLK:PCLK= 400:100:50 (MHz).

1,先配置lock time

我们取芯片手册上的推荐值。
    /* LOCKTIME(0x4C000000) = 0xFFFFFFFF */
    ldr r0, =0x4C000000
ldr r1, =0xFFFFFFFF
str r1, [r0]

2,配置MPLL得到FCLK

也可参考配置表取值

/*
** MPLL(FCLK) = 2*m*Fin/(p*2^s)
** 不妨取:
** m = MDIV+8 = 92+8=100
** p = PDIV+2 = 1+2 = 3
** s = SDIV = 1
** 则:
** FCLK= 2*100*12/(3*2^1)=400M
*/
ldr r0, =0x4C000004
ldr r1, =(92<<12)|(1<<4)|(1<<0)
str r1, [r0]

注意:如果也要配置了UPLL,那么先配置UPLL,要个7个NOP后才能再配置MPLL.

3,配置CLKDIVN得到HCLK,PCLK

/* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8  */
ldr r0, =0x4C000014
ldr r1, =0x5
str r1, [r0]

注意:如果HDIV设置为非0,CPU的总线模式要进行改变,默认情况下FCLK = HCLK,CPU工作在fast bus mode快速总线模式下,HDIV设置为非0后, FCLK与HCLK不再相等,要将CPU改为asynchronous bus mod异步总线模式.

/* 设置CPU工作于异步模式 */
mrc p15, 0, r1, c1, c0, 0 ??????? /* 读取CP15 C1寄存器 */?
orr r1, r1, #0xc0000000 ???????   /* 设置CPU总线模式 */?
mcr p15, 0, r1, c1, c0, 0 ??????? /* 写回CP15 C1寄存器 */

完整代码如下:

.text
.global _start

_start:

/* 关闭看门狗 */
ldr r0, =0x53000000
ldr r1, =0
str r1, [r0]

/* 设置MPLL, FCLK : HCLK : PCLK = 400m : 100m : 50m */
/* LOCKTIME(0x4C000000) = 0xFFFFFFFF */
ldr r0, =0x4C000000
ldr r1, =0xFFFFFFFF
str r1, [r0]

/* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8  */
ldr r0, =0x4C000014
ldr r1, =0x5
str r1, [r0]

/* 设置CPU工作于异步模式 */
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000   //R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0

/* 设置MPLLCON(0x4C000004) = (92<<12)|(1<<4)|(1<<0)
 *  m = MDIV+8 = 92+8=100
 *  p = PDIV+2 = 1+2 = 3
 *  s = SDIV = 1
 *  FCLK = 2*m*Fin/(p*2^s) = 2*100*12/(3*2^1)=400M
 */
ldr r0, =0x4C000004
ldr r1, =(92<<12)|(1<<4)|(1<<0)
str r1, [r0]

/* 一旦设置PLL, 就会锁定lock time直到PLL输出稳定
 * 然后CPU工作于新的频率FCLK
 */

/* 设置内存: sp 栈 */
/* 分辨是nor/nand启动
 * 写0到0地址, 再读出来
 * 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动
 * 否则就是nor启动
 */
mov r1, #0
ldr r0, [r1] /* 读出原来的值备份 */
str r1, [r1] /* 0->[0] */
ldr r2, [r1] /* r2=[0] */
cmp r1, r2
ldr sp, =0x40000000+4096
moveq sp, #4096  /* r1=r2, nand启动,修改栈指针=4096(此时sram对应0地址) */
streq r0, [r1]   /* 恢复原来的值 */

bl main

halt:
b halt

原文地址:https://www.cnblogs.com/fuzidage/p/12001498.html

时间: 2024-10-07 20:17:29

s3c2440裸机编程-时钟编程(二、配置时钟寄存器)的相关文章

s3c2440裸机编程-时钟编程(一、2440时钟体系介绍)

1.总线框架 下图是2440的总线框架,其中有AHB(Advanced High performance Bus)高速总线,APB(Advanced Peripheral Bus)外围总线. 不同总线对应不同的时钟. SOC <-> FCLK AHB <-> HCLK APB <-> PCLK 其中: 1.使用AHB总线的有:LCD控制器.usb控制器.中断控制器.内存控制器等... 2.使用APB总线的有:i2c.spi.timer.gpio.adc等...具体上图.

s3c2440裸机-异常中断(二. und未定义指令异常)

1._und(未定义指令异常)介绍 我们之前分析过5种异常,那么如何进入未定义指令异常,当然是cpu读取指令发生异常,出现了指令解析异常. 我们先来看下当cpu解析到什么样的指令才会触发未定义指令异常呢? 从上面的arm指令格式中可知,只要指令码属于划线的格式,就属于未定义指令异常. 2.汇编向c函数传参 我们知道汇编给C语言函数传参是通过r0,r1,...通过堆栈的方式去传递的参数,比如r0=1, r1=2;那么在被调用的c函数中argv0就是r0, argv1就是r1...,那么我们如果通过

s3c2440裸机-代码重定位(2.编程实现代码重定位)

代码重定位(2.编程实现代码重定位) 1.引入链接脚本 我们上一节讲述了为什么要重定位代码,那么怎么去重定位代码呢? 上一节我们发现"arm-linux-ld -Ttext 0 -Tdata 0x30000000"这种方式编译出来的bin文件有800多M,这肯定是不行的,那么需要怎么把.data段重定位到sdram呢? 可以通过AT参数指定.data段在编译时的存放位置,我们发现这样指定太不方便了,而且不好确定要放在bin文件的哪个位置.这里就要引入链接脚本,它可以帮我们解决这个不必要

C#编程总结(二)多线程基础

C#编程总结(二)多线程基础 无论您是为具有单个处理器的计算机还是为具有多个处理器的计算机进行开发,您都希望应用程序为用户提供最好的响应性能,即使应用程序当前正在完成其他工作.要使应用程序能够快速响应用户操作,同时在用户事件之间或者甚至在用户事件期间利用处理器,最强大的方式之一是使用多线程技术. 多线程:线程是程序中一个单一的顺序控制流程.在单个程序中同时运行多个线程完成不同的工作,称为多线程.如果某个线程进行一次长延迟操作, 处理器就切换到另一个线程执行.这样,多个线程的并行(并发)执行隐藏了

Linux系统裁剪之二(Bash脚本编程之十二)

Linux系统裁剪之二(Bash脚本编程之十二) 系统函数库 ·Linux系统的启动流程     1,POST(加电自检) 计算机本身并不会执行程序,它只是一堆破铜烂铁,但是它可以在开机的时候先去载入一段程序,系统在刚刚启动的时候能够实现将某个ROM芯片中的程序映射到CPU能够寻址的地址空间中去,并且让CPU能够执行其中的指令,这些指令大部分都是用来做系统检测的,当检测完成后,如果系统中所有的基本硬件和核心硬件都没有问题的话,接下来就会根据BIOS中设定的系统启动次序(Boot Sequence

linux下的时钟编程

1.时钟相关的API函数原型 #include <unistd.h> unsigned int sleep(unsigned int seconds); unsigned int alarm(unsigned int seconds); int usleep(useconds_t usec); #include <sys/time.h> int getitimer(int which, struct itimerval *curr_value); int setitimer(int

我的编程之路(二十) 新的环境、新的开始

被其他项目组借用了三个星期,这周终于要给自己的项目组干活了,之前就听同事说过省厅,这次终于要去了,有点激动哈: 1.挤公交 星期二跟着同事一起去省厅,那个公交呀,真是挤呀,以前还庆幸自己上班不用挤公交呢,唉~~~看来这一个多月都要重复着早上7点20起床,7点50挤半个多小时公交的生活了~~~ 2.同事 还记得刚来公司的时候,强哥就跟我说,zqq(一个女生)就做的很好,对自己要求很高,一直在省厅那边,上次我们项目组聚会,第一次见到本人,也见到不少其他同事,那次还自己把自己灌醉了,幸亏宝强哥把我送了

我的编程之路(二十一) 规范

不知不觉一周就过去了,这周细想真的没有做成什么,因为几乎都是做了改,改了做··· 1.代码规范 以前自认为自己很注重代码规范,但是没有想到自己项目组的开发会将代码规范审查的那么严谨,这突然让我想到之前说到程序员都喜欢追求完美,都喜欢自己和自己的风格一致,否则就会觉得别扭,不过与此不同,这是团队开发,代码规范是为了统一风格,便于别人的阅读与后人的修改与维护,虽然因为这我前前后后改了三次dao层的代码,一是要用公司封装的借口,二是要把异常处理都放在这一层或者service层,三是要用公司自己写的工具

Windows API 编程学习记录&lt;二&gt;

恩,开始写Windows API编程第二节吧. 上次介绍了几个关于Windows API编程最基本的概念,但是如果只是看这些概念,估计还是对Windows API不是很了解.这节我们就使用Windows API 让大家来了解下Windows API的用法. 第一个介绍的Windows API 当然是最经典的MessageBox,这个API 的作用就是在电脑上显示一个对话框,我们先来看看这个API的定义吧: int WINAPI MessageBox(HWND hWnd, LPCTSTR lpTe