本文使用的开发板是九鼎创展的X210 iNand版本。
一、S5PV210的时钟系统简介
1、时钟域:MSYS、DSYS、PSYS
因为S5PV210的时钟体系比较复杂,内部外设模块太多,因此把整个内部的时钟划分为三大块,叫做三个时钟域,分别是MSYS、DSYS、PSYS。
因为S5PV210内部的这些模块彼此工作的时钟速率差异太大,因此把高速的放在一起,相对低速的放在一起。
(1)MSYS:CPU(Cortex-A8内核)、DRAM控制器(DMC0和DMC1)、IRAM & IROM等
(2)DSYS:和视频显示、编解码等有关的模块
(3)PSYS:和内部的各种外设时钟有关,例如:串口、SD接口、I2C、AC97、USB等
2、时钟来源:晶振 + 时钟发生器 + PLL + 分频电路
S5PV210外部有四个晶振接口,设计板子硬件时可以根据需要来决定在哪里接晶振。接了晶振之后,上电相应的模块就能产生振荡,产生原始时钟。原始时钟再经过一系列的筛选开关进入相应的PLL电路生成倍频后的高频时钟。高频时钟再经过分频到达芯片内部的各个模块上。
有些模块(串口)内部还有进一步的分频器进行再次分频使用。
3、PLL:APLL、MPLL、EPLL、VPLL
(1)APLL:MSYS域
(2)MPLL:DSYS域
(3)EPLL:PSYS域
(4)VPLL:视频相关模块
4、时钟域和时钟的关系
(1)MSYS域
ARMCLK:给CPU内核工作的时钟,也就是所谓的主频
HCLK_MSYS:MSYS域的高频时钟,给DMC0和DMC1使用
PCLK_MSYS:MSYS域的低频时钟
HCLK_IMEM:给IRAM和IROM(合称IMEM)使用
(2)DSYS域
HCLK_DSYS:DSYS域的高频时钟
PCLK_DSYS:DSYS域的低频时钟
(3)PSYS域
HCLK_PSYS:PSYS域的高频时钟
PCLK_PSYS:PSYS域的低频时钟
SCLK_ONENAND
S5PV210内部的各个外设都是接在内部AMBA总线上面的,AMBA总线有一条高频分支叫AHB,有一条低频分支叫APB。上面的各个域都有各自对应的HCLK_XXXX和PCLK_XXXX,其中HCLK_XXXX就是XXXX域中AHB总线的工作频率,PCLK_XXXX就是XXXX域中APB总线的工作频率。
SoC内部的各个外设其实是挂在总线上工作的,也就是说这个外设的时钟来自于它挂在的总线。例如串口UART挂在PSYS域下的APB总线上,因此串口的时钟来源是PCLK_PSYS。
我们可以通过记住和分析上面的这些时钟域和总线的数值,来确定各个外设的具体时钟频率。
5、各时钟的典型值(IROM中设置的值)
(1)当X210刚上电时,默认是外部晶振 + 内部时钟发生器产生的24MHz频率的时钟直接给ARMCLK的,这时系统的主频就是24MHz。
(2)IROM代码执行时,第六步中初始化了时钟系统,这时给了系统一个默认推荐的运行频率,这个时钟频率是三星推荐的S5PV210工作性能和稳定性最佳的频率。
二、S5PV210的时钟体系框图
(1)两张图之间是渐进的关系。第一张图从左到右依次完成了:原始时钟的生成-->PLL倍频得到高频时钟-->初次分频得到各总线时钟,第二张图是从各个中间时钟(第一张图中某个步骤生成的时钟)到各外设自己使用的时钟(实际就是个别外设自己再额外分频的设置)。
(2)第一张图是理解整个时钟体系的关键,第二张图是进一步分析各外设时钟来源的关键。
(3)要看懂时钟体系框图,两个符号很重要:一个是MUX开关,另一个是DIV分频器。
1)MUX开关就是一个或门,实际对应某个寄存器的某几个bit位的设置,设置值决定了哪条通道是通 的。分析这个可以知道右边的时钟是从左边哪条路过来的,从而知道右边的时钟是多少。
2)DIV分频器是一个硬件设备,可以对左边的频率进行分频,分频后的低频时钟输出到右边。分频器在 编程时实际对应某个寄存器中的某几个bit位。我们可以通过设置这个寄存器的对应bit位来设置分频 器的分频系数。
(4)寄存器中的Clock Source Control Register就是用来设置MUX开关的,Clock Divider Control Register就是用来设置DIV分频器的分频系数的。
三、时钟设置的关键性寄存器
(1)xPLL_LOCK
主要控制PLL的锁定周期
(2)xPLL_CON、xPLL_CON0、xPLL_CON1
主要用来打开 / 关闭PLL电路,设置PLL的倍频参数,查看PLL的锁定状态等
(3)CLK_SRCn(n取值为0~6)
主要用来设置时钟来源,对应时钟体系框图中的MUX开关
(4)CLK_SRC_MASKn
主要用来决定MUX开关n选1后是否能继续通过
(5)CLK_DIVn
主要用来设置各模块的分频器参数
(6)CLK_GATE_n
类似于CLK_SRC_MASKn,对时钟进行开关控制
(7)CLK_DIV_STATn、CLK_MUX_STATn
主要用来查看DIV和MUX的状态是否已经完成还是在进行中
其中最重要的寄存器有三类:CON、SRC、DIV。CON决定PLL倍频到多少,SRC决定MUX走哪一条路,DIV决定分频多少。
四、时钟设置的步骤
1、步骤分析
(1)先选择不使用PLL。让外部的24MHz原始时钟直接过去,绕过APLL那条路
(2)设置锁定时间。
(3)设置分频系数。决定由PLL倍频出来的最高时钟如何分频得到各个分时钟
(4)设置PLL。主要是设置PLL的倍频系数,决定由24MHz的原始时钟可以得到多大的输出频率
(5)打开PLL。前四步已经设置好了所有的开关和分频系数,本步骤打开PLL后,PLL开始工作,锁定频率后输出,然后经过分频得到各个频率。
2、CLK_SRC寄存器的设置分析
CLK_SRC寄存器主要是用来设置MUX开关的,可以先将该寄存器设置为全0,主要是bit0和bit4要设置为0,表示APLL和MPLL暂时都不启用。
3、xPLL_LOCK寄存器的设置分析
xPLL_LOCK寄存器主要是用来设置PLL的锁定周期的,官方的推荐值为0x0FFF。
4、CLK_DIV寄存器的设置分析
我们设置的值是0x14131440,含义分析如下:
PCLK_PSYS = HCLK_PSYS / 2
HCLK_PSYS = MOUT_PSYS / 5
PCLK_DSYS = HCLK_DSYS / 2
HCLK_DSYS = MOUT_DSYS / 4
PCLK_MSYS = HCLK_MSYS / 2
HCLK_MSYS = ARMCLK / 5
SCLKA2M = SCLKAPLL / 5
ARMCLK = MOUT_MSYS / 1
5、APLL和MPLL设置的关键
APLL和MPLL设置的关键都是P、M、S这三个值,我们设置的值都来自于官方数据手册的推荐值。
五、代码实现
1、Makefile
led.bin: start.o led.o clock.o arm-linux-ld -Ttext 0x0 -o led.elf $^ arm-linux-objcopy -O binary led.elf led.bin arm-linux-objdump -D led.elf > led_elf.dis gcc mkv210_image.c -o mkx210 ./mkx210 led.bin 210.bin %.o : %.S arm-linux-gcc -o $@ $< -c -nostdlib %.o : %.c arm-linux-gcc -o $@ $< -c -nostdlib clean: rm *.o *.elf *.bin *.dis mkx210 -f
2、start.S
#define SVC_STACK 0xD0037D80 .global _start _start: // 初始化时钟 bl clock_init ldr sp, =SVC_STACK bl led_blink b .
3、led.c
#define GPJ0CON 0xE0200240 #define GPJ0DAT 0xE0200244 #define rGPJ0CON *((volatile unsigned int *)GPJ0CON) #define rGPJ0DAT *((volatile unsigned int *)GPJ0DAT) void delay(void); void led_blink(void) { rGPJ0CON = 0x11111111; while(1) { // led亮 rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5)); // 延时 delay(); // led灭 rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5)); // 延时 delay(); } } void delay(void) { volatile unsigned int i = 900000; while (i--); }
4、clock.S
// 时钟控制器基地址 #define ELFIN_CLOCK_POWER_BASE 0xE0100000 // 时钟相关的寄存器相对时钟控制器基地址的偏移值 #define APLL_LOCK_OFFSET 0x00 #define MPLL_LOCK_OFFSET 0x08 #define APLL_CON0_OFFSET 0x100 #define APLL_CON1_OFFSET 0x104 #define MPLL_CON_OFFSET 0x108 #define CLK_SRC0_OFFSET 0x200 #define CLK_SRC1_OFFSET 0x204 #define CLK_SRC2_OFFSET 0x208 #define CLK_SRC3_OFFSET 0x20c #define CLK_SRC4_OFFSET 0x210 #define CLK_SRC5_OFFSET 0x214 #define CLK_SRC6_OFFSET 0x218 #define CLK_SRC_MASK0_OFFSET 0x280 #define CLK_SRC_MASK1_OFFSET 0x284 #define CLK_DIV0_OFFSET 0x300 #define CLK_DIV1_OFFSET 0x304 #define CLK_DIV2_OFFSET 0x308 #define CLK_DIV3_OFFSET 0x30c #define CLK_DIV4_OFFSET 0x310 #define CLK_DIV5_OFFSET 0x314 #define CLK_DIV6_OFFSET 0x318 #define CLK_DIV7_OFFSET 0x31c #define CLK_DIV0_MASK 0x7fffffff #define APLL_MDIV 0x7d // 125 #define APLL_PDIV 0x3 // 3 #define APLL_SDIV 0x1 // 1 #define MPLL_MDIV 0x29b // 667 #define MPLL_PDIV 0xc // 12 #define MPLL_SDIV 0x1 // 1 #define set_pll(mdiv, pdiv, sdiv) (1<<31 | mdiv<<16 | pdiv<<8 | sdiv) #define APLL_VAL set_pll(APLL_MDIV,APLL_PDIV,APLL_SDIV) #define MPLL_VAL set_pll(MPLL_MDIV,MPLL_PDIV,MPLL_SDIV) .global clock_init clock_init: ldr r0, =ELFIN_CLOCK_POWER_BASE // 设置各种时钟开关,暂时不使用PLL ldr r1, =0x0 str r1, [r0, #CLK_SRC0_OFFSET] // 设置锁定时间 ldr r1, =0x0000FFFF str r1, [r0, #APLL_LOCK_OFFSET] str r1, [r0, #MPLL_LOCK_OFFSET] // 设置分频 // 清bit[0~31] ldr r1, [r0, #CLK_DIV0_OFFSET] ldr r2, =CLK_DIV0_MASK bic r1, r1, r2 ldr r2, =0x14131440 orr r1, r1, r2 str r1, [r0, #CLK_DIV0_OFFSET] // 设置PLL // FOUT = MDIV * FIN / (PDIV * 2^(SDIV-1)) = 0x7d * 24 / (0x3 * 2^(1-1)) = 1000MHz ldr r1, =APLL_VAL str r1, [r0, #APLL_CON0_OFFSET] // FOUT = MDIV * FIN / (PDIV * 2^SDIV) = 0x29b * 24 / (0xc * 2^1) = 667MHz ldr r1, =MPLL_VAL str r1, [r0, #MPLL_CON_OFFSET] // 设置各种时钟开关,使用PLL ldr r1, [r0, #CLK_SRC0_OFFSET] ldr r2, =0x10001111 orr r1, r1, r2 str r1, [r0, #CLK_SRC0_OFFSET] mov pc, lr
以下为时钟初始化的C语言实现,只需将时钟初始化的相关代码(clock.S)改为C语言实现(clock.c)即可。
// 时钟控制器基地址 #define ELFIN_CLOCK_POWER_BASE 0xE0100000 // 时钟相关的寄存器相对时钟控制器基地址的偏移值 #define APLL_LOCK_OFFSET 0x00 #define MPLL_LOCK_OFFSET 0x08 #define APLL_CON0_OFFSET 0x100 #define APLL_CON1_OFFSET 0x104 #define MPLL_CON_OFFSET 0x108 #define CLK_SRC0_OFFSET 0x200 #define CLK_SRC1_OFFSET 0x204 #define CLK_SRC2_OFFSET 0x208 #define CLK_SRC3_OFFSET 0x20c #define CLK_SRC4_OFFSET 0x210 #define CLK_SRC5_OFFSET 0x214 #define CLK_SRC6_OFFSET 0x218 #define CLK_SRC_MASK0_OFFSET 0x280 #define CLK_SRC_MASK1_OFFSET 0x284 #define CLK_DIV0_OFFSET 0x300 #define CLK_DIV1_OFFSET 0x304 #define CLK_DIV2_OFFSET 0x308 #define CLK_DIV3_OFFSET 0x30c #define CLK_DIV4_OFFSET 0x310 #define CLK_DIV5_OFFSET 0x314 #define CLK_DIV6_OFFSET 0x318 #define CLK_DIV7_OFFSET 0x31c #define CLK_DIV0_MASK 0x7fffffff #define APLL_MDIV 0x7d // 125 #define APLL_PDIV 0x3 // 3 #define APLL_SDIV 0x1 // 1 #define MPLL_MDIV 0x29b // 667 #define MPLL_PDIV 0xc // 12 #define MPLL_SDIV 0x1 // 1 #define set_pll(mdiv, pdiv, sdiv) (1<<31 | mdiv<<16 | pdiv<<8 | sdiv) #define APLL_VAL set_pll(APLL_MDIV,APLL_PDIV,APLL_SDIV) #define MPLL_VAL set_pll(MPLL_MDIV,MPLL_PDIV,MPLL_SDIV) #define REG_CLK_SRC0 (ELFIN_CLOCK_POWER_BASE + CLK_SRC0_OFFSET) #define REG_APLL_LOCK (ELFIN_CLOCK_POWER_BASE + APLL_LOCK_OFFSET) #define REG_MPLL_LOCK (ELFIN_CLOCK_POWER_BASE + MPLL_LOCK_OFFSET) #define REG_CLK_DIV0 (ELFIN_CLOCK_POWER_BASE + CLK_DIV0_OFFSET) #define REG_APLL_CON0 (ELFIN_CLOCK_POWER_BASE + APLL_CON0_OFFSET) #define REG_MPLL_CON (ELFIN_CLOCK_POWER_BASE + MPLL_CON_OFFSET) #define rREG_CLK_SRC0 (*(volatile unsigned int *)REG_CLK_SRC0) #define rREG_APLL_LOCK (*(volatile unsigned int *)REG_APLL_LOCK) #define rREG_MPLL_LOCK (*(volatile unsigned int *)REG_MPLL_LOCK) #define rREG_CLK_DIV0 (*(volatile unsigned int *)REG_CLK_DIV0) #define rREG_APLL_CON0 (*(volatile unsigned int *)REG_APLL_CON0) #define rREG_MPLL_CON (*(volatile unsigned int *)REG_MPLL_CON) void clock_init(void) { // 设置各种时钟开关,暂时不使用PLL rREG_CLK_SRC0 = 0x0; // 设置锁定时间 rREG_APLL_LOCK = 0x0000ffff; rREG_MPLL_LOCK = 0x0000ffff; // 设置分频 rREG_CLK_DIV0 = 0x14131440; // 设置PLL // FOUT = MDIV * FIN / (PDIV * 2^(SDIV-1)) = 0x7d * 24 / (0x3 * 2^(1-1)) = 1000MHz rREG_APLL_CON0 = APLL_VAL; // FOUT = MDIV * FIN / (PDIV * 2^SDIV) = 0x29b * 24 / (0xc * 2^1) = 667MHz rREG_MPLL_CON = MPLL_VAL; // 设置各种时钟开关,使用PLL rREG_CLK_SRC0 = 0x10001111; }
相关推荐
以下是关于"S5PV210初始化系统时钟"的详细知识讲解。 首先,我们要理解S5PV210的时钟架构。S5PV210有一个复杂的时钟管理系统,它由多个振荡器、锁相环(PLL)、分频器和倍频器组成。系统时钟通常来自外部晶体振荡器...
在本文中,我们将深入探讨如何使用汇编语言对三星S5PV210处理器进行时钟初始化,这是嵌入式系统开发中的一个关键步骤。三星S5PV210是一款基于ARM Cortex-A8架构的高性能微处理器,广泛应用于智能手机、平板电脑和...
中断系统是S5PV210处理器中非常重要的组成部分,它负责处理处理器内部以及外部的各种事件通知,确保处理器能够及时响应这些事件。 在S5PV210中断系统中,共有93个中断源,这些中断源被组织成4组。每个中断源对应一...
在S5PV210数据手册中,我们能找到关于Cortex-A8内核的详细信息,如CPU时钟频率、内存接口、电源管理、中断控制器等关键模块的描述。这些信息对于理解和配置芯片至关重要。例如,手册会详细介绍如何通过配置寄存器来...
S5PV210是一款由三星公司推出的高性能、低功耗的ARM Cortex-A8处理器,广泛应用于嵌入式系统、移动设备以及智能硬件等领域。对于学习和开发基于S5PV210的系统,理解其源码是至关重要的一步。这篇笔记将深入探讨S5PV...
【S5PV210 PWM定时器】是三星公司推出的一款基于ARM Cortex-A8处理器的SoC(系统级芯片)中的重要硬件模块。PWM(Pulse Width Modulation,脉宽调制)定时器在嵌入式系统中广泛用于电机控制、LED亮度调节、模拟信号...
【基于s5pv210的时钟程序】是一个针对特定硬件平台的系统级软件开发项目,主要目标是实现和管理设备的时钟系统。s5pv210是一款由Samsung公司推出的高性能ARM Cortex-A8处理器,常用于嵌入式系统,如智能设备和消费...
描述中提到"S5PC110 S5PV210 clock controller register offsets"表明内容着重于S5PV210时钟控制器的寄存器偏移量,这对于理解处理器内部时钟系统的工作原理至关重要。 S5PV210是一款由三星(Samsung)推出的高性能...
S5PV210是一款由Samsung开发的高性能ARM Cortex-A8核心的系统级芯片(SoC),广泛应用于嵌入式系统和开发板中。u-boot作为开源的引导加载程序,对于这类硬件平台至关重要,它负责初始化硬件、加载操作系统内核,以及...
在嵌入式系统领域,S5PV210是一款由Samsung公司推出的高性能ARMCortex-A8处理器,广泛应用于各种嵌入式设备,如智能手机、平板电脑等。在本主题中,我们将深入探讨如何利用S5PV210的Timer0模块来输出PWM信号,进而...
S5PV210是三星公司开发的一款基于ARM Cortex-A8内核的系统级芯片(SoC),它集成了多种接口,包括SPI,用于与其他设备进行数据交换。STM32则是意法半导体(STMicroelectronics)生产的一系列基于ARM Cortex-M内核的...
3. **C语言实现**:在描述中提到的博客文章中,作者使用C语言编写了内存初始化代码,这涉及到对S5PV210的系统寄存器操作。例如,通过设置`MPLLCON`寄存器来调整内存总线的频率,通过`DRAMCON`寄存器设定DDR的时序...
- **移动设备**: 智能手机和平板电脑是S5PV210的主要应用场景之一,其高性能和低功耗特性非常适合这类设备。 - **车载信息系统**: 由于具备强大的多媒体处理能力,S5PV210也被广泛应用于汽车娱乐系统。 - **数字标牌...
S5PV210是一款由三星公司开发的高性能、低功耗的应用处理器,广泛应用于嵌入式系统,如智能手机和平板电脑。SPI(Serial Peripheral Interface)是一种常见的串行通信协议,用于连接微控制器和其他外围设备。在S5PV...
标题"S5PV210应用原理图"和描述"SMDK_S5PV210_CPU B'd (S5PV210 Evaluation Board) Schematics"指出我们关注的是S5PV210评估板的原理图。S5PV210是三星电子生产的一款具有高性能的多媒体处理器,广泛应用于平板电脑...
`arch/arm/mach-s5pv210` 文件夹下则是与S5PV210架构相关的代码,包括处理器初始化、时钟管理等。 在进行 BSP(Board Support Package)开发时,开发者需要根据实际硬件调整UBOOT源码中的配置,比如设置正确的内存...
总之,S5PV210三星原厂Windows CE BSP是开发者构建基于S5PV210平台的Windows CE系统的重要工具,它提供了全面的硬件支持,优化了系统性能,简化了开发流程。理解并熟练运用BSP中的各个组件,是成功开发和调试嵌入式...
S5PV210是一款高性能的ARM Cortex-A8处理器,由三星电子研发,广泛应用于智能手机、平板电脑和嵌入式系统等设备中。这款处理器以其强大的处理能力、低功耗设计以及丰富的接口选项而受到业界的青睐。在深入理解S5PV...