才开始学嵌入式没多久,用得友善之臂的2440板子,前段时间一直在搞linux系统,软件移植,内核裁剪等,最近发现还是应该从最基本的学起,想自己写
一个bootloader,然后就研究了友善之臂那个板子上光盘里面配的一个示例程序,哎,搞了一天多才研究出来一点点东西,贴上来,免得忘了!
S3C2440启动过程(约略):
1、关闭watch dog
2、屏蔽所有中断
3、屏蔽所有子中断
4、设置时钟更改稳定等待时间(LOCKTIME)
5、设置各部件时钟频率与CPU主频的比例关系(Fclk:Hclk:Pclk)
6、设置USB总线时钟频率(UPLLCON)
7、nap * 7
8、设置主时钟(MPLLCON)
9、判断是否是从睡眠状态唤醒的,如果是,则做出相应处理(具体处理还没看)
10、初始化存储设备、包括外存,内存等(BWSCON,BANKCONn,BANKSIZE,MRSRB6,MRSRB7)
11、初始化处理器各模式的堆栈(还没看懂)
12、Setup IRQ handler(也没咋看懂,似乎是对IRQ终端进行处理)
13、进入C程序(bl Main)
代码分析:
;=========================================; NAME: 2440INIT.S; DESC: C start up codes; Configure memory, ISR ,stacks; Initialize C-variables; HISTORY:; 2002.02.25:kwtark: ver 0.0; 2002.03.20:purnnamu: Add some functions for testing STOP,Sleep mode; 2003.03.14:DonGo: Modified for 2440.; 2009.02.19:PuHao: Comments;=========================================;=========================; ENTRY 这里是关键的入口,正文数量超过最大限制,只有忽略其他我没看懂的了,等下能不能把那个文件传上来,好恶心的规定……;=========================ResetHandler
;WTCON定义在2440addr.inc里面,WTCON EQU 0x53000000
;把WTCON地址放到R0里,然后在设置r1为0,最后把r1中的0值
;拷贝到r0所指向的地址里面,即禁用watch dog
ldr r0,=WTCON ;watch dog disable
ldr r1,=0x0
str r1,[r0]
;基本同上,INTMSK 0x4A000008 R/W Interrupt mask control
ldr r0,=INTMSK
ldr r1,=0xffffffff ;all interrupt disable
str r1,[r0]
;基本同上
ldr r0,=INTSUBMSK
ldr r1,=0x3ff ;all sub interrupt disable,0x3ff => 0000 0011 1111 1111
str r1,[r0]
;由于条件为FALSE,我觉得这段根本就不会执行
[ {FALSE}
; rGPFDAT = (rGPFDAT & ~(0xf<<4)) | ((~data & 0xf)<<4);
; Led_Display
ldr r0,=GPFCON
ldr r1,=0x5500
str r1,[r0]
ldr r0,=GPFDAT
ldr r1,=0x10
str r1,[r0]
]
;由于在更改了主时钟控制器(MPLL)之后,新的频率需要一定时间过后才能稳定
;所以需要等待一段时间,而这个等待的时间就是使用LOCKTIME寄存器来设置的
;LOCKTIME[15:00] MPLL lock time count value for FCLK, HCLK, and PCLK
;LOCKTIME[32:16] UPLL lock time count value for UCLK.
; FCLK用于CPU核
; HCLK用于AHB总线的设备(比如SDRAM)
; PCLK用于APB总线的设备(比如UART)
; UPLL为USB的控制时钟,根据USB规范,好像是48MHz
; ARM920T内核使用FCLK
; 内存控制器,LCD控制器等使用HCLK;
; 看门狗、串口等使用PCLK
;To reduce PLL lock time, adjust the LOCKTIME register.
ldr r0,=LOCKTIME
ldr r1,=0xffffff ;0000 0000 1111 1111 1111 1111 1111 1111
str r1,[r0] ;为什么UPLL的等待时间要少一些呢?
[ PLL_ON_START
; Added for confirm clock divide. for 2440.
; Setting value Fclk:Hclk:Pclk
; 这里设置的 Fclk:Hclk:Pclk = 1:3:6,因为 CLKDIV_VAL = 7
ldr r0,=CLKDIVN
ldr r1,=CLKDIV_VAL ; 0=1:1:1, 1=1:1:2, 2=1:2:2, 3=1:2:4, 4=1:4:4, 5=1:4:8, 6=1:3:3, 7=1:3:6.
str r1,[r0]
;UPLL和MPLL的控制参数
;PLLCON Bit Description Initial State
;MDIV [19:12] Main divider control 0x96 / 0x4d
;PDIV [9:4] Pre-divider control 0x03 / 0x03
;SDIV [1:0] Post divider control 0x0 / 0x0
;InputFrequency OutputFrequency MDIV PDIV SDIV
;12.0000MHz 48.00 MHz(Note) 56(0x38) 2 2
;12.0000MHz 96.00 MHz(Note) 56(0x38) 2 1
;12.0000MHz 271.50 MHz 173(0xad) 2 2
;12.0000MHz 304.00 MHz 68(0x44) 1 1
;12.0000MHz 405.00 MHz 127(0x7f) 2 1
;12.0000MHz 532.00 MHz 125(0x7d) 1 1
;Configure UPLL
; 根据手册,要对PLL进行设置的话,就需要先设置UPLLCON,再设置MPLLCON
; 并且中间需要有至少七个指令周期的延时
; (Needs intervals approximately 7 NOP)
; U_MDIV EQU 56 ;Fin=12.0MHz Fout=48MHz
; U_PDIV EQU 2
; U_SDIV EQU 2
ldr r0,=UPLLCON
ldr r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)
str r1,[r0]
;(Needs intervals approximately 7 NOP)
nop ; Caution: After UPLL setting, at least 7-clocks delay must be inserted for setting hardware be completed.
nop
nop
nop
nop
nop
nop
;Configure MPLL
; M_MDIV EQU 68 ; 68 = 0x44 Fin=12.0MHz Fout=304.8MHz
; M_PDIV EQU 1
; M_SDIV EQU 1 ; 2440A
; 设为(0x44 << 12)|(0x01 << 4)|(0x01),即0x00044011
; Fclk:Hclk:Pclk = 1:3:6 => Fclk = 300MHz, Hclk = 100MHz, Pclk = 50MHz
;
ldr r0,=MPLLCON
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV)
str r1,[r0]