U-Boot 在44B0X 开发板上的移植以及代码分析
时间:11-11
来源:互联网
点击:
uartz=11MHz) */
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
ldr r0, =0x610c1 /*B2: Xtal=20mhz Fclk=75MHz */
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif
str r0, [r1]
ldr r1,=CLKCON
ldr r0, =0x7ff8
str r0, [r1]
mov pc, lr
4) 初始化SDRAM控制器
内存控制器(主要是SDRAM控制器),主要通过设置13 个从1c80000 开始的寄存器来设置,包括总线宽度,8 个内存bank,bank 大小,sclk,以及两个bank mode。
#ifdef CONFIG_INIT_CRITICAL
bl cpu_init_crit
/*
* before relocating, we have to setup RAM timing
* because memory timing is board-dependend, you will
* find a memsetup.S in your board directory.
*/
bl memsetup
#endif
初始化内存控制器的代码存放在u-boot-1.1.2/board/gold44b/memsetup.S中
与ADS或者SDT下的boot代码(memcfg.s和44binit.s)一致,只是汇编格式有点不一样。
5) 将rom 中的程序复制到RAM 中
首先利用PC 取得bootloader 在flash 的起始地址,再通过标号之差计算出这个程序代
码的大小。这些标号,编译器会在连接(link)的时候生成正确的分布的值。取得正
确信息后,通过寄存器(r3 到r10)做为复制的中间媒介,将代码复制到RAM 中。
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* dont reloc during debug */
beq stack_setup
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
6) 初始化堆栈
进入各种模式设置相应模式的堆栈.
/* Set up the stack */
stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack */
7) 转到RAM 中执行
使用指令ldr,pc,RAM 中C 函数地址就可以转到RAM 中去执行。
ldr pc, _start_armboot
5. 系统初始化部分
1) 串口部分(u-boot-1.1.2/cpu/s3c44b0/serial.c)
串口的设置主要包括初始化串口部分,值得注意的串口的Baudrate 与时钟MCLK 有很大关系,是通过:rUBRdiv0=( (int)(MCLK/16./(gd ->baudrate) + 0.5) -1 )计算得出。这可以在手册中查到。由于u-boot支持可变的波特率,所以采用宏定义设置默认波特率(64Mhz,115200bps)和其他波特率。代码如下:
void serial_setbrg (void)
{
DECLARE_GLOBAL_DATA_PTR;
u32 divisor = 0;
/* get correct divisor */
switch(gd->baudrate) {
case 1200:
#if CONFIG_S3C44B0_CLOCK_SPEED==66
divisor = 3124;
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
divisor = 3905;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64 /默认
divisor = 3332;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif
break;
case 9600:
#if CONFIG_S3C44B0_CLOCK_SPEED==66
divisor = 390;
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
divisor = 487;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64 /默认
divisor = 416;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif
break;
case 19200:
#if CONFIG_S3C44B0_CLOCK_SPEED==66
divisor = 194;
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
divisor = 243;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64 /默认
divisor = 207;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif
break;
case 38400:
#if CONFIG_S3C44B0_CLOCK_SPEED==66
divisor = 97;
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
divisor = 121;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64 /默认
divisor = 103;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif break;
case 57600:
#if CONFIG_S3C44B0_CLOCK_SPEED==66
divisor = 64;
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
divisor = 80;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64 /默认
divisor = 68;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif break;
case 115200:
#if CONFIG_S3C44B0_CLOCK_SPEED==66
divisor = 32;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64
divisor = 34;
#elif CONFIG_S3C44B0_CLOCK_SPEED==75 /默认
divisor = 40;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif break;
}
serial_flush_output();
serial_flush_input();
UFCON0 = 0x0;
ULCON0 = 0x03;
UCON0 = 0x05;
UBRdiv0 = divisor;
UFCON1 = 0x0;
ULCON1 = 0x03;
UCON1 = 0x05;
UBRdiv1 = divisor;
for(divisor=0; divisor<100; divisor++) {
/* NOP */
}
}
其他的函数包括发送,接收。这个时候没有中断,是通过循环等待来判断是否动作完成。
例如,接收函数:
static int serial_flush_input(void)
{
volatile u32 tmp;
/* keep on reading as long as the receiver is not empty */
while(UTRSTAT0&0x01) {
tmp = REGB(URXH0);
}
return 0;
}
2) 时钟部分(u-boot-1.1.2/cpu/s3c44b0/interrupt.c)
实现了延时函数udelay。
这里的get_timer 由于没有使用中断,是使用
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
ldr r0, =0x610c1 /*B2: Xtal=20mhz Fclk=75MHz */
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif
str r0, [r1]
ldr r1,=CLKCON
ldr r0, =0x7ff8
str r0, [r1]
mov pc, lr
4) 初始化SDRAM控制器
内存控制器(主要是SDRAM控制器),主要通过设置13 个从1c80000 开始的寄存器来设置,包括总线宽度,8 个内存bank,bank 大小,sclk,以及两个bank mode。
#ifdef CONFIG_INIT_CRITICAL
bl cpu_init_crit
/*
* before relocating, we have to setup RAM timing
* because memory timing is board-dependend, you will
* find a memsetup.S in your board directory.
*/
bl memsetup
#endif
初始化内存控制器的代码存放在u-boot-1.1.2/board/gold44b/memsetup.S中
与ADS或者SDT下的boot代码(memcfg.s和44binit.s)一致,只是汇编格式有点不一样。
5) 将rom 中的程序复制到RAM 中
首先利用PC 取得bootloader 在flash 的起始地址,再通过标号之差计算出这个程序代
码的大小。这些标号,编译器会在连接(link)的时候生成正确的分布的值。取得正
确信息后,通过寄存器(r3 到r10)做为复制的中间媒介,将代码复制到RAM 中。
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* dont reloc during debug */
beq stack_setup
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
6) 初始化堆栈
进入各种模式设置相应模式的堆栈.
/* Set up the stack */
stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack */
7) 转到RAM 中执行
使用指令ldr,pc,RAM 中C 函数地址就可以转到RAM 中去执行。
ldr pc, _start_armboot
5. 系统初始化部分
1) 串口部分(u-boot-1.1.2/cpu/s3c44b0/serial.c)
串口的设置主要包括初始化串口部分,值得注意的串口的Baudrate 与时钟MCLK 有很大关系,是通过:rUBRdiv0=( (int)(MCLK/16./(gd ->baudrate) + 0.5) -1 )计算得出。这可以在手册中查到。由于u-boot支持可变的波特率,所以采用宏定义设置默认波特率(64Mhz,115200bps)和其他波特率。代码如下:
void serial_setbrg (void)
{
DECLARE_GLOBAL_DATA_PTR;
u32 divisor = 0;
/* get correct divisor */
switch(gd->baudrate) {
case 1200:
#if CONFIG_S3C44B0_CLOCK_SPEED==66
divisor = 3124;
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
divisor = 3905;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64 /默认
divisor = 3332;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif
break;
case 9600:
#if CONFIG_S3C44B0_CLOCK_SPEED==66
divisor = 390;
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
divisor = 487;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64 /默认
divisor = 416;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif
break;
case 19200:
#if CONFIG_S3C44B0_CLOCK_SPEED==66
divisor = 194;
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
divisor = 243;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64 /默认
divisor = 207;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif
break;
case 38400:
#if CONFIG_S3C44B0_CLOCK_SPEED==66
divisor = 97;
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
divisor = 121;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64 /默认
divisor = 103;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif break;
case 57600:
#if CONFIG_S3C44B0_CLOCK_SPEED==66
divisor = 64;
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
divisor = 80;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64 /默认
divisor = 68;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif break;
case 115200:
#if CONFIG_S3C44B0_CLOCK_SPEED==66
divisor = 32;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64
divisor = 34;
#elif CONFIG_S3C44B0_CLOCK_SPEED==75 /默认
divisor = 40;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif break;
}
serial_flush_output();
serial_flush_input();
UFCON0 = 0x0;
ULCON0 = 0x03;
UCON0 = 0x05;
UBRdiv0 = divisor;
UFCON1 = 0x0;
ULCON1 = 0x03;
UCON1 = 0x05;
UBRdiv1 = divisor;
for(divisor=0; divisor<100; divisor++) {
/* NOP */
}
}
其他的函数包括发送,接收。这个时候没有中断,是通过循环等待来判断是否动作完成。
例如,接收函数:
static int serial_flush_input(void)
{
volatile u32 tmp;
/* keep on reading as long as the receiver is not empty */
while(UTRSTAT0&0x01) {
tmp = REGB(URXH0);
}
return 0;
}
2) 时钟部分(u-boot-1.1.2/cpu/s3c44b0/interrupt.c)
实现了延时函数udelay。
这里的get_timer 由于没有使用中断,是使用
U-Boot44B0X开移植代码分 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)