http://www.cnblogs.com/zhangsufeng/archive/2011/09/07/2169399.html
最近正在看任哲《嵌入式操作系统基础》,里面的一节内容标题是:“操作系统的内核是由中断驱动的”,所以研究一个新的系统,首先要从系统时钟和定时器的实现开始。
下面一段内容主要来自s3c6410数据手册:
s3c6410的系统控制器(System Controller)分为两大部分组成,系统时钟控制器(System Clock Control)和系统电源管理控制器(System Powet-management Control).系统时钟控制器通过三个PLL(Phase Locked Loop锁相环)生成系统需要的时钟信号,如APLL仅生成用于cpu的ARMCLK,MPLL生成HCLK和PCLK(HCLK用于AXI/AHB总线外设,PCLK用于APB总线外设),EPLL生成的时钟主要用于外设IP,例如UART,IIS,IIC等。
关于系统时钟的配置和使用,我们先从其调用接口来分析,切入实现文件:
cpu\s3c64xx\s3c6410\speed.c
我们这里先分析其使用,再分析其配置。
这里实现了对外的接口:get_ARMCLK() get_FCLK() get_HCLK() get_PCLK() get_UCLK()
除了print_cpuinfo函数调用之外,对外被用到的接口是get_HCLK和get_PCLK.
用到get_HCLK的文件为cpu\s3c64xx\ata.c和cpu\s3c64xx\hs_mmc.c
用到get_PCLK的文件为cpu\s3c64xx\i2c.c和cpu\s3c64xx\interrupts.c
通过查看makefile,ata.c没有编译到。
hs_mmc.c为高速mmc控制器(SD卡)相关功能,需要学习的相关文件为common\Cmd_movi.c和cpu\s3c64xx\movi.c,开启sd卡启动宏CONFIG_BOOT_MOVINAND后,初始化顺序为:start_armboot->movi_init->hsmmc_init
i2c.c实现i2c,在CONFIG_HARD_I2C功能下,uboot下未进行i2c_init,后续实验来研究。
Interrupts.c初始化顺序为:start_armboot->init_sequence[]->interrupt_init,initial PWM Timer ,uboot主干框架太简单了,只有一个主循环程序和一个定时器来检测输入超时则启动kernel,即reset_cmd_timeout使用到pwm的get_ticks和get_tbclk函数。
此时再去看datasheet 3.4.2.1 PLL Control Registers 3.4.2.2 Clock Source Control Registers 3.4.2.3 Clock Divider Control Registers以及启动代码
board\samsung\smdk6410\
lowlevel_init.S中system_clock_init:段代码,
1 /*
2 * system_clock_init: Initialize core clock and bus clock.
3 * void system_clock_init(void)
4 */
5 system_clock_init:
6 ldr r0, =ELFIN_CLOCK_POWER_BASE /* 0x7e00f000 */
7
8 #ifdef CONFIG_SYNC_MODE
9 ldr r1, [r0, #OTHERS_OFFSET]
10 mov r2, #0x40
11 orr r1, r1, r2
12 str r1, [r0, #OTHERS_OFFSET]
13
14 nop
15 nop
16 nop
17 nop
18 nop
19
20 ldr r2, =0x80
21 orr r1, r1, r2
22 str r1, [r0, #OTHERS_OFFSET]
23
24 check_syncack:
25 ldr r1, [r0, #OTHERS_OFFSET]
26 ldr r2, =0xf00
27 and r1, r1, r2
28 cmp r1, #0xf00
29 bne check_syncack
30 #else /* ASYNC Mode */
31 nop
32 nop
33 nop
34 nop
35 nop
36
37 /*
38 * This was unconditional in original Samsung sources, but it doesn't
39 * seem to make much sense on S3C6400.
40 */
41 #ifndef CONFIG_S3C6400
42 ldr r1, [r0, #OTHERS_OFFSET]
43 bic r1, r1, #0xC0
44 orr r1, r1, #0x40
45 str r1, [r0, #OTHERS_OFFSET]
46
47 wait_for_async:
48 ldr r1, [r0, #OTHERS_OFFSET]
49 and r1, r1, #0xf00
50 cmp r1, #0x0
51 bne wait_for_async
52 #endif
53
54 ldr r1, [r0, #OTHERS_OFFSET]
55 bic r1, r1, #0x40
56 str r1, [r0, #OTHERS_OFFSET]
57 #endif
58
59 mov r1, #0xff00
60 orr r1, r1, #0xff
61 str r1, [r0, #APLL_LOCK_OFFSET]
62 str r1, [r0, #MPLL_LOCK_OFFSET]
63
64 /* Set Clock Divider */
65 ldr r1, [r0, #CLK_DIV0_OFFSET]
66 bic r1, r1, #0x30000
67 bic r1, r1, #0xff00
68 bic r1, r1, #0xff
69 ldr r2, =CLK_DIV_VAL
70 orr r1, r1, r2
71 str r1, [r0, #CLK_DIV0_OFFSET]
72
73 ldr r1, =APLL_VAL
74 str r1, [r0, #APLL_CON_OFFSET]
75 ldr r1, =MPLL_VAL
76 str r1, [r0, #MPLL_CON_OFFSET]
77
78 /* FOUT of EPLL is 96MHz */
79 ldr r1, =0x200203
80 str r1, [r0, #EPLL_CON0_OFFSET]
81 ldr r1, =0x0
82 str r1, [r0, #EPLL_CON1_OFFSET]
83
84 /* APLL, MPLL, EPLL select to Fout */
85 ldr r1, [r0, #CLK_SRC_OFFSET]
86 orr r1, r1, #0x7
87 str r1, [r0, #CLK_SRC_OFFSET]
88
89 /* wait at least 200us to stablize all clock */
90 mov r1, #0x10000
91 1: subs r1, r1, #1
92 bne 1b
93
94 /* Synchronization for VIC port */
95 #if defined(CONFIG_SYNC_MODE)
96 ldr r1, [r0, #OTHERS_OFFSET]
97 orr r1, r1, #0x20
98 str r1, [r0, #OTHERS_OFFSET]
99 #elif !defined(CONFIG_S3C6400)
100 /* According to 661558um_S3C6400X_rev10.pdf 0x20 is reserved */
101 ldr r1, [r0, #OTHERS_OFFSET]
102 bic r1, r1, #0x20
103 str r1, [r0, #OTHERS_OFFSET]
104 #endif
105 mov pc, lr
1 #if defined(CONFIG_CLK_400_100_50)
2 #define STARTUP_AMDIV 400
3 #define STARTUP_MDIV 400
4 #define STARTUP_PDIV 6
5 #define STARTUP_SDIV 1
6 #elif defined(CONFIG_CLK_400_133_66)
7 #define STARTUP_AMDIV 400
8 #define STARTUP_MDIV 533
9 #define STARTUP_PDIV 6
10 #define STARTUP_SDIV 1
11 #elif defined(CONFIG_CLK_533_133_66)
12 #define STARTUP_AMDIV 533
13 #define STARTUP_MDIV 533
14 #define STARTUP_PDIV 6
15 #define STARTUP_SDIV 1
16 #elif defined(CONFIG_CLK_667_133_66)
17 #define STARTUP_AMDIV 667
18 #define STARTUP_MDIV 533
19 #define STARTUP_PDIV 6
20 #define STARTUP_SDIV 1
21 #endif
22
23 #define STARTUP_PCLKDIV 3
24 #define STARTUP_HCLKX2DIV 1
25 #define STARTUP_HCLKDIV 1
26 #define STARTUP_MPLLDIV 1
27 #define STARTUP_APLLDIV 0
28
29 #define CLK_DIV_VAL ((STARTUP_PCLKDIV << 12) | (STARTUP_HCLKX2DIV << 9) | \
30 (STARTUP_HCLKDIV << 8) | (STARTUP_MPLLDIV<<4) | STARTUP_APLLDIV)
31 #define MPLL_VAL ((1 << 31) | (STARTUP_MDIV << 16) | \
32 (STARTUP_PDIV << 8) | STARTUP_SDIV)
33 #define STARTUP_MPLL (((CONFIG_SYS_CLK_FREQ >> STARTUP_SDIV) / \
34 STARTUP_PDIV) * STARTUP_MDIV)
35
36 #if defined(CONFIG_SYNC_MODE)
37 #define APLL_VAL ((1 << 31) | (STARTUP_MDIV << 16) | \
38 (STARTUP_PDIV << 8) | STARTUP_SDIV)
39 #define STARTUP_APLL (((CONFIG_SYS_CLK_FREQ >> STARTUP_SDIV) / \
40 STARTUP_PDIV) * STARTUP_MDIV)
41 #define STARTUP_HCLK (STARTUP_MPLL / (STARTUP_HCLKX2DIV + 1) / \
42 (STARTUP_HCLKDIV + 1))
43 #else
44 #define APLL_VAL ((1 << 31) | (STARTUP_AMDIV << 16) | \
45 (STARTUP_PDIV << 8) | STARTUP_SDIV)
46 #define STARTUP_APLL (((CONFIG_SYS_CLK_FREQ >> STARTUP_SDIV) / \
47 STARTUP_PDIV) * STARTUP_AMDIV)
48 #define STARTUP_HCLK (STARTUP_MPLL / (STARTUP_HCLKX2DIV + 1) / \
49 (STARTUP_HCLKDIV + 1))
50 #endif
参考
http://www.linuxidc.com/Linux/2011-09/42027.htm
和下面datasheet图进行理解。
(上图:关键信息,fin相关内容见:
http://bbs.eeworld.com.cn/thread-133065-1-1.html
)